JBoss Seam tutorial 2

Several Java EE APIs (EJB, JSF, etc.), as well as popular open source frameworks like Spring, make use of the concept of dependency injection. Injection involves the automatic, runtime insertion of a property value into a bean. This simple concept can greatly simplify development, especially in a Java EE environment.  

The Seam component model also supports a more general version of dependency injection, called bijection. Standard dependency injection involves a one-time initialization of a bean reference within a component, typically done by some kind of container or other runtime service.

Seam introduces the notion of bijection as a generalization of injection.

In contrast to injection, bijection is:

  • contextual - bijection is used to assemble stateful components from various different contexts (a component from a "wider" context may even have a reference to a component from a "narrower" context)
  • bidirectional - values are injected from context variables into attributes of the component being invoked, and also outjected from the component attributes back out to the context, allowing the component being invoked to manipulate the values of contextual variables simply by setting its own instance variables
  • dynamic - since the value of contextual variables changes over time, and since Seam components are stateful, bijection takes place every time a component is invoked

 

Before seeing Seam bijection, let's see what is Simple Injection, from an Example 

@Name("MyBean") 
public class MyBean { 
@In 
private OtherBean otherBean; 

  public SomeBean getOtherBean() { 
   return otherBean;
  }
  public void setOtherBean(OtherBean b) 
 { 
  otherBean = b; 
 } 
}

Here, we’re annotating the formBean property on the Seam component MyBean, telling Seam to inject the value of this property whenever MyBean is invoked. In this case, we’re using @In with no arguments to inject an otherBean instance in MyBean class.


By default, Seam will search all of its contexts for a component with the same name as the annotated property "otherBean." : the first one it finds (in an ordered search of contexts, starting from the event context and ending with application context) is used as the value of the annotated property. If no component of the given name is found anywhere, the injection will not happen, and the property will remain uninitialized.

JBoss Seam Bijection

As mentioned at the start of this section, Seam extends simple injection by introducing the concept of outjection, or the export of a component value from one component back into the scope where the component lives.

Let's recall our previous Registration example and add some spice to it. The User Entity Bean will stay the same, we won't change our model. Rather we add a new Stateless Bean, UserAction

@Stateless 
@Name("useraction") 

public class UserAction implements UserItf { 
@In @Out private User user; 
@Out private List userList; 

@PersistenceContext private EntityManager em; 

 public String addAndDisplay() { 
  em.persist (user); 
  user = new User (); 
  userList = em.createQuery("From User u order by u.name").getResultList(); 
  return null; 
 }

 

The useraction component in Seam is the UserAction session bean, as specified by the @Name annotation on the class. The UserAction class has user and userList fields annotated with the @In and @Out annotations.


The @In and @Out annotations are at the heart of the Seam programming model. So, let's look at exactly what they do here.

The @In annotation tells Seam to assign the user component, which is composed from the JSF form data, to the user field (dependency injection) before executing any method in the session bean. You can specify an arbitrary name for the injected component in @In. But if there is no named specified, as it is here, Seam will just inject the component with the same type and same name as the receiving field variable. 

The @Out annotations tell Seam to assign values of the userList and user fields to the managed components of the same names after any method execution. We call this action "dependency outjection" in Seam. This way, in the addAndDisplay method, we simply need to update the user and userList field values and they will be automatically available on the web page.

So the addAndDisplay() method simply saves the fields to the database via the JPA EntityManager,then it refreshes the user and userList objects, which are outjected after the method exits. The addAndDisplay() returns null to indicate that the current JSF page will be re-displayed with the most up-to-date model data after the call.
 

In short, bijection lets you alias a context variable to a component instance variable, by specifying that the value of the instance variable is injected, outjected, or both.

This is the hello.xhtml view

<f:view>
         <h:form>Please enter your info:<br/>
         
                  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:commandButton type="submit" value="Add User" action="#{useraction.addAndDisplay}"/>
         </h:form>
        
         <h:dataTable value="#{userList}" var="u"> 
           <h:column>   
             <h:outputText value="#{u.username}"/>&nbsp; 
             <h:outputText value="#{u.name}"/>&nbsp; 
           </h:column>
         </h:dataTable>
</f:view>

 

As you can see, the datatable references the userList, which is populated in the addAndDisplayMethod by the following query 

userList = em.createQuery("From User u order by u.name").getResultList();  

 
Picture 1: Seam bijection depicted
jboss seam tutorial

 

Getter / Setter Based Bijection

In the above example, we demonstrated Seam bijection against field variables. You can also biject components against getter and setter methods. For instance, take a look at the following code:

private User user; 
private List userList; 

 @In public void setUser (User user) {
   this.user = user; 
 } 
 @Out public User getUser () { 
  return user; 
 } 
 @Out public List getUserList () { 
  return userList; 
 }

You may wonder why not complicating so much the lift with getter/setter bijection ?
the real value of this change is that you can add custom logic to manipulate the bijection process.
For instance, you can validate the injected object or retrieve the outjected object on the fly from the database.
{fcomment}

Follow us on Twitter