JBoss Seam tutorial 1

To be useful, your application has to be a multi tiered application that uses specific components for the presentation, business, and persistence tiers.
If you have already developed one multi tiered 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 beautiful 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 dramatically 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:

http://www.seamframework.org/Download

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:

<web-app>
. . .
 <listener>
  <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
 </listener>
. . .
</web-app>

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:

<faces-config>
. . .
 <lifecycle>
  <phase-listener>org.jboss.seam.jsf.SeamPhaseListener</phase-listener>
 </lifecycle>
. . .
</faces-config>

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.

<ejb-jar>
. . .
 <assembly-descriptor>
  <interceptors>
   <interceptor>
    <interceptor-class>
          org.jboss.seam.ejb.SeamInterceptor
    </interceptor-class>
   </interceptor>
  </interceptors>
  <interceptor-binding>
   <ejb-name>*</ejb-name>
    <interceptor-class>
          org.jboss.seam.ejb.SeamInterceptor
    </interceptor-class>
  </interceptor-binding>
</assembly-descriptor>
. . .
</ejb-jar>

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
server

<?xml version="1.0" encoding="UTF-8"?>
<components xmlns="http://jboss.com/products/seam/components"
            xmlns:core="http://jboss.com/products/seam/core"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation=
                "http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.0.xsd
                 http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.0.xsd">

    <core:init jndi-pattern="@jndiPattern@"/>

</components>

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

      <f:view>
         <h:form>
            <s:validateAll>
               <h:panelGrid columns="2">
                  Username: <h:inputText value="#{user.username}" required="true"/>
                  Real Name: <h:inputText value="#{user.name}" required="true"/>
                  Password: <h:inputSecret value="#{user.password}" required="true"/>
               </h:panelGrid>
            </s:validateAll>
            <h:messages/>
            <h:commandButton value="Register" action="#{register.registerUser}"/>
         </h:form>
      </f:view>

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:

package org.jboss.seam.example.registration;

import static org.jboss.seam.ScopeType.SESSION;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.validator.Length;
import org.hibernate.validator.NotNull;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;

@Entity
@Name("user")
@Scope(SESSION)
@Table(name="users")
public class User implements Serializable
{
   private static final long serialVersionUID = 1881413500711441951L;
   
   private String username;
   private String password;
   private String name;
   
   public User(String name, String password, String username)
   {
      this.name = name;
      this.password = password;
      this.username = username;
   }
   
   public User() {}
   
   @NotNull
   public String getName()
   {
      return name;
   }

   public void setName(String name)
   {
      this.name = name;
   }
   
   @NotNull @Length(min=5, max=15)
   public String getPassword()
   {
      return password;
   }

   public void setPassword(String password)
   {
      this.password = password;
   }
   
   @Id @NotNull @Length(min=5, max=15)
   public String getUsername()
   {
      return username;
   }

   public void setUsername(String username)
   {
      this.username = username;
   }
   
   @Override
   public String toString() 
   {
      return "User(" + username + ")";
   }
}

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.

jboss seam ejb

Picture 1: presentation tier invoke the RegisterAction EJB.

package org.jboss.seam.example.registration;

import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.log.Log;

import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.datamodel.DataModel;

@Stateless
@Name("register")
public class RegisterAction implements Register
{

   @In
   private User user;
   
   @PersistenceContext
   private EntityManager em;
   
   @Logger
   private static Log log;
   
   @DataModel
   private List items=null;
    
   
   public String registerUser()
   {
      
         em.persist(user);
         log.info("Registered new user #{user.username}");
         return "/registered.jspx";
      
   }

   @Factory("items")
    public void getItems() {
        List list = em.createQuery("From User u order by u.name").getResultList();
        items = list;
   }

}

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()

<h:dataTable var="u" value="#{items}" rendered="#{items.rowCount>0}">
        <h:column>

         <f:facet name="header">
            <h:outputText value="username"/>
         </f:facet>
          <h:outputText value="#{u.username}"/>

        </h:column>

        <h:column>

         <f:facet name="header">
            <h:outputText value="password"/>
         </f:facet>
          <h:outputText value="#{u.password}"/>

        </h:column>
           
</h:dataTable>

So when JSF meets the variable “items” will delegate to the @Factory method getItems which will simply create a List of User objects.

   @Factory("items")
    public void getItems() {
        List list = em.createQuery("From User u order by u.name").getResultList();
        items = list;
   }

Once instantiated the list will be stored in the variable

@DataModel
    private List<User> items=null;

when this is clear, retrieving the single fields is just a piece of cake

<h:outputText value="#{u.username}"/>
 <h:outputText value="#{u.password}"/>

jboss seam ejb

Picture 2: Data is queried using the RegisterAction’s Factory method.

JBoss Seam Project picture:

So this is how our Seam application looks like. 
jboss seam tutorial
Picture 3: How a typical Seam project is made up.

Before packing, in the jboss-seam-registration.jar you need to add a seam property file: the seam.properties file is empty here but it is required for JBoss to know that this JAR file contains Seam EJB3 bean classes, and process the annotations accordingly.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

   <persistence-unit name="userDatabase">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>java:/DefaultDS</jta-data-source>
      <properties>
         <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      </properties>
   </persistence-unit>

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 !

Stay tuned….in a few days you’ll learn quite a lot of things with the next….

JBoss seam tutorial part 2

Found the article helpful? if so please follow us on Socials