Monday, November 19, 2007

Seam Tip Number 4

Seam Tip Number 4 : @In(required = false) pitfall

In retrospect this is really obvious, but a member variable annotated with @In will be overwritten in subsequent invocations of a Stateful Session Bean even with a "required = false" on the annotation.

I had assumed that the "required = false" would prevent the variable from being injected if it wasn't present, but that isn't the case.


Blogged with Flock

Wednesday, November 7, 2007

NumberFox

This is a completely cool Firefox plugin that Neal Ford mentioned in his Productivity talk at No Fluff Just Stuff (I was at the Atlanta one.)

Clicking ctrl + z or ctrl + w will display small, numbered boxes next to the clickable elements in a page. You can then click the link by clicking the number and enter from the keyboard.

Blogged with Flock

Tuesday, October 30, 2007

Seam Tip Number 3

Seam Tip Number 3

This isn't so much a tip, but a "gotcha" to avoid.

Make sure that you have an <h:messages /> tag in your page and that it does not have "globalOnly" set to "true."

I spent a lot of time wondering my my method wasn't getting called when the problem was a not null value being trapped.

Blogged with Flock

Wednesday, October 24, 2007

Seam Tip Number 2

Seam Tip Number 2

Keep insert statements inside the import.sql file on the same line.

One of the coolest things about developing in Seam is the "create-drop" setting for data. 

If you create your project with seam-gen and choose "y" for the prompt, "Do you want to drop and recreate the database tables and data in import.sql each time you deploy?" there will be three files, import-dev.sql, import-test.sql and import-prod.sql.  The data in these files will be used to populate tables generated from your entities.  You can of course do this manually, but I want to be brief.

I mocked up some data and redeployed, but I wasn't seeing anything when I hit the page.  Watching the log files after restarting the server showed an sql error on import which turned out to be the line break.  I was using Eclipse to edit the file so I found that odd, but stranger things have of course happened.  I removed the line breaks and everything worked.

Blogged with Flock

Tuesday, October 23, 2007

Seam Tip Number 1

Seam Tip Number 1

Seam-gen saves your defaults in the build.properties (Ant of course) file inside the [Seam dist]/seam-gen folder. 

If like me you have accidentally typed the wrong directory for your project workspace or the wrong directory for your db driver jar file, simply edit the build.properties and the defaults will change.


Seam-gen is a cool part of JBoss Seam.  From the Seam docs,
"This is the easy way to get your feet wet with Seam, and gives you some ammunition for next time you find yourself trapped in an elevator with one of those tedious Ruby guys ranting about how great and wonderful his new toy is for building totally trivial applications that put things in databases."

Blogged with Flock

Code is design

Everyone has heard the line, "The older I get the more I realize my father was right."  This a cliche of course, but I'm reminded of it pretty often now that I have kids of my own.

The Too Much Code blog, which I found on DZone this morning, reminded me of this.  Unless I have a selective memory, more selective than the average anyway, I remember hearing that we developers needed a complete design before we started coding.  I still hear that a lot actually despite the success of Pragmatic Programmers, XP, Scrum, etc.

I don't remember people telling me that big up front software design was a bad idea, and the older that I get the more I think it is at best a waste of time and worst a serious project risk.

From Too Much Code :
"If we accept that code is design -- a creative process rather than a mechanical one -- the software crisis is explained. Now we have a design crisis: the demand for quality, validated designs far exceeds our capacity to create them. The pressure to use incomplete design is strong."

From the articles (same link as in the quote) that he references,
"We must keep in mind, however, that these tools and notations (UML, CRC Cards, Booch diagrams) are not a software design. Eventually, we have to create the real software design, and it will be in some programming language. Therefore, we should not be afraid to code our designs as we derive them."

Too bad my father never told me anything about software development.

Blogged with Flock

Friday, October 19, 2007

Seam Lifecycle

I've been playing with JBoss' Seam for a brief while now. I've used Struts for years so I'm completely familiar with its' action based lifecycle. I have considerably less experience with JSF. Knowing a framework's lifecycle is definitely useful, and I wanted a diagram of Seam's.

This article from IBM Developerworks has a gif diagram that nicely outlines Seam's enhancements to the JSF lifecycle. I printed it out and tacked it onto my cube.

Blogged with Flock

Wednesday, October 10, 2007

Seam-gen and TestNG problems

I created a project using Seam-gen, taking the database defaults (I wanted hsqldb for development anyway.)

First thing I wrote a test for the Manager/Action class that I was starting with. I also added a testng.xml to the src/test folder. I was using Eclipse so I right clicked on the build.xml's test target and ran it. Nothing.

The testng.xml file wasn't get copied to the test-build directory so I updated the build.xml withe the following :
  • test target - changed line 315 to read <xmlfileset dir="${test.dir}" includes="testng.xml" /> instead of <xmlfileset dir="${test.dir}" includes="*Test.xml" />
  • copytestclasses target - added <include name="*.xml" /> in the last copy statement so that the testng.xml file was copied from classes/test directory along with the class files
  • copytestclasses target - removed "if='eclipse.running'" from the target. I don't know why, but the files weren't copied at all with this qualifier even though I was running out of Eclipse.
The test ran from build.xml.

Right clicking and running the TestNG plugin didn't do anything though. I opened the Run dialog (Run -> Open Run Dialog) and updated the classpath of the TestNG test to include the lib/test folder and ran the test from there. I got a different but no better result. (The stack trace is pasted below in the possibly vain belief that someone may stumble onto this posting while Googling the same problem)

javax.persistence.PersistenceException: org.hibernate.HibernateException: The chosen transaction strategy requires access to the JTA TransactionManager
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:737)
at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:121)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:60)

I found this entry on JBoss' Forums which suggested using a non-jta-data-source in the persistence-test.xml. I updated my persistence-test.xml to the following (changes in bold) :

<?xml version="1.0" encoding="UTF-8"?>
<!-- Persistence deployment descriptor for tests -->
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">

<persistence-unit name="project_name" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<non-jta-data-source>java:/DefaultDS</non-jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.show_sql" value="true"/>
<property name="jboss.entity.manager.factory.jndi.name" value="java:/project_nameEntityManagerFactory"/>
</properties>
</persistence-unit>

</persistence>

That did the trick; although, it doesn't appear that my test data is getting loaded. I'll blog that solution later.

Blogged with Flock

Tuesday, October 9, 2007

Seam and TestNG and a missing rar file

Generated a new project with seam-gen.

Had a problem with the build.xml's "test" task. I got the error "You need to specify at least one testng.xml or one class"

I downloaded last night's snapshot from JBoss. (On a side note, I've started using Hudson after seeing it used by JBoss, and its very nice. I like it more than Continuum and CruiseControl.) Same error.

I added a testng.xml file to src/test directory.

I changed buildxml :
added "<include name="**/*.class"/>" to line 282
added "<copy tofile="${test.dir}/testng.xml" file="${src.test.dir}/testng.xml" overwrite="true"/>" to line 296.
changed line 320 (324 after adding the above) to "<xmlfileset dir="${test.dir}" includes="testng.xml" />"

The test ran, which was good; however, there were errors in the output.
"Error parsing meta data jboss-local-jdbc.rar"

Looking through the output I noticed that there was an io.FileNotFound for "C:\Documents%20%and%20%Settings." The actual file was referenced correctly in several of the other lines, but I decided to start over with seam-gen and put the folder directly on the C drive with no spaces.

It worked.

The moral : put my Eclipse workspaces on the C drive.

Blogged with Flock

Monday, September 17, 2007

Seam, Enums and Select Boxes

While building a form I wanted the option elements inside a select to reflect the values of an Enum that I had.

I tried giving an @Name annotation to the Enum, which didn't work.  This post on the JBoss forums explained that Enums can't be instantiated and therefore can't be used as a Seam component.  I felt sort of dumb for trying that and decided to implement the suggested solution.

I built the piece I was working on from the "stateful" example from Michael Yuan's book, Jboss Seam : Power and Simplicity Beyond Java EE (Amazon link). My form was on "main.xhtml" and was submitting to "ManagerAction" which implemented "Manager" interface.  The Enum I wanted for the select was "ServiceTicketStatus." 

I added the following to my ManagerAction class,

@Factory("serviceTicketStatuses")
   public ServiceTicketStatus[] getServiceTicketStatuses()
   {
      return ServiceTicketStatus.values();
   }

and this to the Manager interface,

public ServiceTicketStatus[] getServiceTicketStatuses();

and this to the form in main.xhtml,

<h:selectOneMenu id="searchStatus"  value="#{manager.statusSearch}" >
    <f:selectItem itemValue="" itemLabel="Please Select" />
    <s:selectItems value="#{serviceTicketStatuses}" var="statuses" />
</h:selectOneMenu>

It worked as advertised.

Blogged with Flock

Wednesday, September 12, 2007

Another cool thing about JBoss Seam : The s:selectItems tag

I've been using JBoss Seam and reading JBoss Seam : Power and Simplicity Beyond Java EE (Amazon link). I've been working through the examples from Michael Yuan's site and tweaking the "Stateful" example into something resembling my current project.

I just came across the Seam JSF Controls.  The s:selectItems tag is really nice.  It converts a List of Objects, in my case a List<String> into a List<SelectItem>.

The more I use Seam the more impressed I am with the way it addresses the headaches of JSF and web development.

Blogged with Flock

Thursday, August 30, 2007

Seam Error Messages

I've been reading JBoss Seam : Power and Simplicity Beyond Java EE (Amazon link) and working through the examples from Michael Yuan's site.

After playing with the example from Chapter 6 : A Simple Stateful Application, I decided to change the ManagerAction class from a session scoped variable to a conversation scoped variable.

I changed "@Scope(SESSION)" to "@Scope(CONVERSATION)", added a "@Begin" to the "sayHello()" method, and added "@End" to the "startOver()" method and redeployed.

I had breakpoints set inside the sayHello and startOver methods and was debugging in Eclipse Europa.  I wanted to watch the memory addresses of the ManagerAction over multiple submits to verify that different browser tabs would spawn different conversations.

The change didn't work.  I got,

14:22:29,544 FATAL [application] javax.ejb.EJBException: java.lang.IllegalStateException: begin method invoked from a long running conversation, try using @Begin(join=true) on method: sayHello

I decided to follow the error message's advice.  It worked -- nice error message!

I started two conversations in two browser tabs, the urls displayed differenct conversation ids, and Eclipse showed different memory addresses when I hit the breakpoints.  However, when I entered different one word names, "Bill" and "Mickey" (I was listening to DeadPod) and tried different responses to the prompt, I encountered a problem.  When I would choose the "Oops, let me go back and change" option the name would be the same in both windows.

I checked the Person object, and it was session scoped.  I removed the @Scope annotation and everything worked as expected.

Hibernate often throw nice error messages, and I'm glad to see that has been carried over to Seam.  Nice work!


Blogged with Flock

Friday, August 10, 2007

Enabling the HSQLD / Hypersonic console in JBoss 4.2.0.GA

Enabling the HSQLD / Hypersonic console in JBoss
  • Uncomment lines 16, 90 and 95-103 of hsqldb-dx.xml. The server should pick up the change to the file and reload.
  • Open up the jmx-console (http://localhost:8080/jmx-console if running locally.)
  • Click on the "service=Hypersonic" link under jboss.
  • Click the "Invoke" button under "void startDatabaseManager()" which should be the third MBean operation.

Blogged with Flock