Skip to main content

Seam Refresh

Posted by bleonard on June 15, 2007 at 9:45 AM PDT

It's been over a year since I first wrote about Seam and enough has changed over that time to provide a refresh of the entry. Last month JBoss released version 4.2 of its application server, a release JBoss refers to as a "stepping stone from JBoss 4.0 to JBoss 5.0". One notable difference with JBoss 4.2 is that is now uses the JSF Reference Implementation from GlassFish rather than the Apache MyFaces implementation, which makes porting an application between the 2 servers all the more straight-forward.

To introduce Seam, I use the same Registration application that JBoss uses in their Seam tutorial. I take a different approach, however, in that my version of the Registration application is pure Java EE 5 (no Seam), and then I walk you step-by-step through the changes necessary to configure the application to use the Seam framework. I also use this approach for a presentation I often give titled "Refactoring to Seam". You can view a draft of my slides for the upcoming Jazoon conference.


Setting Things Up

  • Download and extract JBoss 4.2.0 GA
  • Download and install GlassFish V1, following the instructions on the download page. Alternatively you can use Sun Java System Application Server PE 9, Sun's GlassFish distribution.
  • Download and extract Seam 1.2.1 GA
  • Download and install NetBeans 5.5.1
  • Download and extract the Registration project

Add the JBoss 4.2 Server to NetBeans

  1. Start NetBeans and switch to the Runtime window (Ctrl+5).
  2. Right-click the Servers node and select Add Server.
  3. Select JBoss Application Server and add 4.2 to the end of the Name. This will just help distinguish it from other versions of JBoss that you may already have installed.






  4. Click Next and browse to the location where you extracted JBoss 4.2. Click Next and Finish.
  5. Right-click the JBoss Application Server 4.2 node and select Start.

Add the GlassFish Server to NetBeans

  1. Add another server, this time selecting Sun Java System Application Server (Sun's binary distribution of GlassFish). Change the Name to GlassFish V1.
  2. Browse to the location where you installed GlassFish and select Finish.

Open and Test Run the Registration Project

The Registration application is a NetBeans Enterprise Application Project, which is actually comprised of 3 projects: Registration, Registration-EJBModule and Registration-WebModule. Registration-EJBModule and Registration-WebModule are Java EE Modules of the Registration project. Registration-EJBModule generates the EJB jar file. Registration-WebModule generates the war file and Registration generates the ear file which contains the jar and war.

  1. Open the Registration project. The Enterprise Application Project stores the absolute location to its
    J2EE Modules. So, unless you extracted your project to the exact same
    location as me, you will see this dialog when you open the project.






  2. Click Close. The Registration project will be in bold red.
  3. Right click the project and select Resolve Reference Problems from the context menu.






  4. Use the Resolve Reference Problems dialog to map each module to its project, which you'll find are subdirectories beneath the Registration directory:






  5. After the references are resolved, right-click the Registration project and select Open Required Projects (now that the dependencies are correct, these dependent projects will always open for you).






  6. However, there are still additional references problems with the EJB and web modules. The problem with the EJB module is that it references a couple of JSF jar files that are needed to build the project. Generally these libraries are included as part of the server, but with JBoss 4.2 they've been moved to a different location and NetBeans didn't pick them up. See issue 106346.



    Right-click the Registration-EJBModule to resolve the reference problems and browse to the server\default\deploy\jboss-web.deployer\jsf-libs directory of your JBoss server installation, select jsf-api.jar and select Open. This should also cause jsf-impl.jar to be resolved:







    Click Close.


  7. The problem with the Web module is that it has a reference to the EJB module. Right-click the Registration-WebModule and select Resolve Reference Problems. Browse to the Registration-ejb directory which is a sub-directory below the Registration directory and select Open Project Folder.






  8. All references should now be resolved. Press F6 to test run the project. NetBeans will build, package, deploy and launch the application for you:







    It's a simple application, but it will demonstrate a lot of the functionality provided by the Seam framework, such as:

    • Elimination of the Managed Bean - we will be able to completely eliminate our managed bean. Our web module will no longer contain any java files.
    • Validation - Username and Password require and entry between 5 and 15 characters. We'll be able to specify these requirements in our entity class, rather then in our JSP.

Refactoring To Seam

Step 1: Add And Integrate The Seam Framework Into The Project

In this step we're only going to integrate the required Seam components so that we can begin using the framework. We won't actually start using Seam until the next step. If NetBeans had direct support for the Seam framework, this is the stuff you'd expect the IDE to do for you.

Create the Seam Library

  1. Open the Library Manager (Tools menu) and create a new library called JBossSeam.
  2. Set the Classpath to jboss-seam.jar.
  3. Set the Sources to the JBoss Seam src directory.
  4. Set the Javadoc to the JBoss Seam doc directory.


    This library is now available for use by any project.

Configure the EJB Module for Seam

Add the Seam Library To Your Project

  1. Right-click the Libraries node of the Registration-EJBModule project and choose Add Library.
  2. Add the JBossSeam library to the project.

Add the seam.properties file

The seam.properties is empty, but Seam will not work without it.

  1. Press Ctrl+N to create a new file. Make sure Registration-EJBModule is selected as the project and select the Other Category > Properties File File Type.
  2. Name the file seam and put it in the src\conf Folder.

Configure the Web Module for Seam

Configure faces-config.xml

  1. Open phases-config.xml and add the following phase listener:



     version="1.2" 
    ...
    >
            >
                org.jboss.seam.jsf.SeamPhaseListener
           
    >
       
    >
    >

Configure web.xml

  1. Add the following Context Parameter to web.xml:

         Param Name: org.jboss.seam.core.init.jndiPattern

         Param Value: registration/#{ejbName}/local



         



    Note, the Seam examples you see on JBoss' web site now configure the JNDI pattern in components.xml. For this simple application however, I hate to use yet another xml configuration file, so I'm doing it in web.xml.



  2. Add the following Web Application Listener: org.jboss.seam.servlet.SeamListener.



Test Your Changes

We haven't actually done anything yet with Seam, but we want to make sure our app still runs and we'll use the log to verify Seam was loaded successfully.

  1. Press F6 to run the project. The registration application should run successfully and you should see an entry like the following in the JBoss log file:



    2007-06-13 20:35:06,281 INFO [javax.servlet.ServletContextListener] Welcome to Seam 1.2.1

Step 2: Name our Enterprise Components and Eliminate the Managed Bean

Mapping Directly to the Entity Class

In this section we're going to give the Java EE 5 components a name so that they can be managed by the Seam framework. If we look at our faces-config.xml, our managed bean is named "user" and has a "request" scope.



We're going to provide the Seam framework with this information using annotations on our User entity class.

  1. Open User.java and add 2 new annotations: @Name("user") and @Scope("ScopeType.EVENT)







    The SeamListener will now map the JSF "user" context variable directly to our entity class, bypassing our managed bean, and set the scope of the context variable to request.

Mapping Directly to the Action Class

Currently, JSF calls our managed bean with in turn calls our action class. If we give our action class a name, we can bind to it directly from JSF, like we did with the entity class.

  1. Open RegisterActionBean.java and add a Name annotation: @Name("register")







  2. Open register.jsp and change the action on the command button from user.register (the call to our managed bean) to register.register (the call directly to our action class).



One problem with this change is that action methods in JSF cannot pass arguments, which was fine for the register method in our managed bean, as it passed the arguments onto our action class:







No that we no longer have a managed bean, how do we get these arguments into our action class?



The answer is that Seam will allow us to inject the named user context object into our action class.

  1. Use Seam's @In annotation to inject a user field into RegisterActoinBean.java. The Seam framework will use EJB interceptors to perform the injection, so we add the following @Interceptors annotation to the class as well: @Interceptors({org.jboss.seam.ejb.SeamInterceptor.class}).







    Note, the interceptor could alternatively be configured in ejb-jar.xml, and for a larger application with more EJBs I would put it there (this is the approach I used in my original blog on Seam). However, for this simple, single EJB application, I'm able to avoid yet another xml configuration file by using the Interceptors annotation directly on the class.


  2. Remove the arguments from the register method and pull the necessary values from the injected user field. Note, we also no longer need to instantiate a new user if one doesn't exist - Seam will do this for us. Your updated method should look as follows:






  3. Don't forget to update the register method signature in the RegisterActionLocal interface.

Delete the Managed Bean

  1. Delete the managed bean (you can just delete the entire org.example.jsf package).
  2. Delete the managed-bean entry from faces-config.xml.

Test The Seam Managed Application

  1. Press F6 to run the application. It should behave exactly as it did before, yet, under the covers, it's now using Seam.



    Here's the completed application now using the Seam framework. You'll have to resolve the same reference problems as you did above.

Working with the Hibernate Validator

Our application already uses JSF validators to provide validation:



 

However, it's better to move the responsibility for maintaining these requirements onto the model, which the Seam framework will allow us to do because it incorporates the Hibernate Validator framework, which works regardless of your persistence provider (we'll see this when we run on GlassFish next). Try the following:

  1. Add the Hibernate Validator's @Length(min=5, max=15) annotations to the getUsername() and getPassword() methods of the User.java entity class






  2. Switch to the Registration-WebModule, Right-click the Libraries node, and select Add JAR/Folder.







    Add the jboss-seam-ui.jar found in the root of where you extracted the Seam framework. Alternatively, you could create a library like we did above for jboss-seam.jar and add the library to the project.



    jboss-seam.ui.jar includes the taglibs that handle the validation based on the Hibernate Validator annotations.


  3. Open register.jsp and below the 2 existing taglib entries type tglb+space, which inserts the taglib code template. Your cursor should now be between the quotes of the uri property. Press ctrl+space to open the code completion and select the seam taglib.






  4. Set the prefix to "s". The completed entry will look as follows:






  5. Insert a new line before the tag and type to open code completion for the Seam tag library, were you'll find information for all of the available tags in the Seam library. Select the tag.






  6. Insert the closing tag after the closing
  7. tag.


  8. You can now delete the Faces length validators. Your JSP should now look as follows:






  9. Press F6 to test the project using the Hibernate validators:







    You can tell it's using the Hibernate Validators because the messages returned are a bit different.



    Here's the completed application with validation.

Running the Application on GlassFish

  1. Stop the JBoss Application Server (because it shares the same port as GlassFish).
  2. Start the GlassFish server.

Switch the Runtime Server to GlassFish

  1. Right-click the Registration project and choose Properties.
  2. Select the Run category and change the Server from JBoss to GlassFish.
  3. Repeat this step for both the EJB and Web modules.

Update the Persistence Unit

We'll update the persistence unit to use the persistence manager (TopLink) and database (Java DB) bundled with GlassFish.

  1. Open persistence.xml
  2. Change the Data Source to jdbc/sample.
  3. Change the Table Generation Strategy to Drop and Create.
  4. Save and close the file.

Add Additional Seam Libraries

Seam is relying on a couple of additional libraries that are already included with JBoss, such as the Hibernate Validator framework.

  1. Right-click the EJB module's Libraries node and select Add JAR/Folder. Browse to the Seam lib directory and add hibernate-all.jar and thirdparty-all.jar.

Adjust web.xml

  1. Update the org.jboss.seam.core.init.jndiPattern to java:comp/env/registration/#{ejbName}/local.
  2. Switch to the References page and add the following EJB Reference:



Run the Registration Project on GlassFish

That's it. The application will now run on GlassFish.

  1. Press F6 to run the project:







    Here's the completed application configured for GlassFish.
Related Topics >>