To be useful, your application has to be a multitiered application that uses specific components for the presentation, business, and persistence tiers.
If you have already developed one multitiered application you know that lots of time is devoted to writing lots of "glue" code in order to connect your tier.
Starting from the presentation layer, in your forms you'll reference your JSF Beans, your JSF Beans will in turn reference your Business classes, your Business classes will call your EJB maybe passing some wrapper Java Bean classes, your EJB will finally reach your DAO layer and do datapersistence.
So how can JBoss Seam help me ? I guess you already have asked yourself: why cannot I reference my EJB directly from my JSP page ?
Let me tell you, Seam it's not only about this, but the same way when you want to conquer a location in a battle you need a bridgehead, so that's your bridgehead.
Imagine how beatiful would be if in your JSP form you could reference directly your Entity Beans field, you push "Submit" and the data goes straight on the DB.
Imagine next if you need to query the data, simply reference your Session Bean doQuery Method.
Seam achieves this by eliminating the need for "plumbing" code. Essentially, we are allowing Seam to handle the plumbing and to have the business logic interact with the JSF pages themselves. One of the nice things about Seam is that even if you already have code you want to use, you will be able to
keep your existing EJBs and JSF pages, thus being able to maintain a mixed environment if you choose.
How can Seam do it ? to keep it simple, Seam uses Interceptors at all layer levels. By using interceptors you're allowed to use Seam specific annotations into already-existing classes. This will cut drammatically the time needed to develop "glue" code and leaving more time to spend actually developing the business functionality.
So let's get how hands dirty, first of all download Seam from the distribution:
In this release we will use the stable 2.0.3 CR1 release. Now let's see first in detail how to configure Seam Listeners.
I ) web.xml - Seam Servlet Listener
In order to initialize the Seam core services and to correctly manage some Seam contexts that are in common with standard web container contexts, you have to install the Seam servlet listener in your web.xml deployment descriptor:
Ok, that's one, let's go on.
II ) faces-config.xml - JSF Phase Listener
At the heart of Seam's component and context services is the Seam JSF phase listener. It receives events from the JSF runtime during request processing, allowing Seam to keep its various contexts in their proper state, among other things.
The Seam phase listener is installed in your faces-config.xml file:
III ) ejb-jar.xml - EJB Seam Interceptor
The last tier that needs Seam glue is the EJB-tier. Here we'll use the old ejb-jar.xml. (Thought you got rid of it, isn't it ?) Here we just define SeamInterceptor for all the EJBs but of course you could choose to use it only for a subset of them.
The Seam interceptor allows EJB components to be used as Seam components, by "plugging" them into the Seam component life cycle when you annotate your EJBs with the Seam @Name annotation.
JNDI pattern : Seam's components.xml
In order for Seam to work with the EJB container, you need to include an entry for Seam's core initialization component, and this entry needs to include a setting for the JNDI pattern that Seam should use to find your application's EJB components in the JNDI services of the application server.
The following example shows how this setting is provided for the JBoss application
Seam Registration Example reloaded
Here we'll use on example application provided with Seam distribution but we'll add a few additions to make it more interesting. The example is located under the "registration" example folder. Let's start from the Home page, register.xhtml
Well if you're practical with JSF you'll notice nothing strange except..how does JSF resolves the "user" and "register" fields ? You say in a configuration file ? wrong answer!. JBoss Seam uses , as well as EJB 3.0, a lot of annotations. Let's see our User Entity Bean and you'll understand better:
As we said, Jboss seam needs a component name specified by the @Name annotation. This name must be unique within the Seam application. So JSF when meets the variable "user" delegates Seam to resolve a context variable with a name "user".
When Seam instantiates the component, it binds the new instance of a User to a context variable in the component's default context. The default context is specified using the @Scope annotation. In our case the User bean is a session scoped component
Our Entity Bean has a façade which will be accessed by our clients. The façade is a standard Stateless Session Bean, but with special Jboss Seam Annotations.
Picture 1: presentation tier invoke the RegisterAction EJB.
Let's see in detail: well about the "name" annotation we have already discussed,
The @In annotation marks an attribute of the bean as injected by Seam. In this case, the attribute is injected from a context variable named user (the instance variable name).
The Seam @Logger annotation is used to inject the component's Log instance.
Let's move on the registerUser: this is the core method of the application which persist the data on the DB. Notice that it has no parameters because the Bean is injected with the @In annotation.
Maybe you have noticed that this method contains a redirection: well you may asking what happened to JSF navigation rules ? well they still exist but Seam has a nice shortcut which is useful for small application : you can simply return the view as the outcome, eliminating the requirement for a navigation rule. For larger applications of course is better to keep a higher level of indirection and so using navigation rules
Last piece of the puzzle are @DataModel and the @Factory annotation
Data models are pretty handy components when it's necessary to display database data onto a presentation tier. This allows you a fairly simple way to look up the data, determine the selected row, and use it for computations and display purposes.
As you'll see the DataModel will be used to populate the JSF DataTable element with the Values provided in the @Factory method getItems()
So when JSF meets the variable "items" will delegate to the @Factory method getItems which will simply create a List of User objects.
Once instantiated the list will be stored in the variable
when this is clear, retrieving the single fields is just a piece of cake
Picture 2: Data is queried using the RegisterAction's Factory method.
JBoss Seam Project picture:
So this is how our Seam application looks like.
Picture 3: How a typical Seam project is made up.
One thing you might wonder what is the file is how do you connect to your Datasource: well that’s managed by the persistence.xml file which simply points to the Default HSQL Datasource
If you want to build this application, the easiest way is simply replace the files that you find under the registration example provided with the Seam distribution. Siimply build and deploy your project with ant and you're done !