Seam
From Shrubbery
The Basics
Links and tips about JBoss SEAM.
- Seam Configuration Files: http://wiki.jboss.org/wiki/Wiki.jsp?page=SeamConfigurationFiles
- JSF basic components: http://www.exadel.com/tutorial/jsf/jsftags-guide.html
- Seam walkthrough: http://www-128.ibm.com/developerworks/java/library/j-seam1/index.html
- Seam introduction: http://www.javabeat.net/jboss-seam/2007/06/jboss-seam-introduction/
Understanding Seam Contexts
See Understanding Seam Contexts
Cool Stuff that Seam Does
Well, Seam does a whole lot of cool stuff. Here are the things that I thought were important.
Conversations, EJB Extended Persistence Contexts and Transactions
In EJB3 a persistence context (managed entities in an EntityManager) can extend beyond transaction boundaries when used inside a stateful EJB, comitting only when needed. This persistence context forms a convenient 'cache' of all the objects in the unit of work (from the user's perspective). This allows Web/EJB3 applications to completely avoid the constant re-loading of entities on every single web request-response cycle. What Seam does is integrate this nearly transparently into the JSF layer by allowing stateful EJBs to be managed in a Seam context scope, the most interesting scope being conversation scope.
Seam also provides built in components for switching and cancelling long running conversations. This is a huge win over designing this kind of thing yourself.
- Users can leave activities partially finished and return to them later or cancel them.
- Developers can build user interfaces to allow users to do this kind of thing with zero Java code . Just access the built in components in the view.
Seam works with Ajax4JSF
Seam can be used with the Ajax4JSF UI components in order to make the web UI more.
- Configuring Seam and Ajax4JSF - https://ajax4jsf.dev.java.net/nonav/documentation/ajax-documentation/ch03s05.html
Seam Application Framework
Write less code! The Seam application framework provides built in components that allow you to pretty much just write the entity and the view. The framework takes care of doing all the business logic class.
http://docs.jboss.com/seam/latest/reference/en/html/framework.html
Security with Seam
- http://wiki.jboss.org/wiki/Wiki.jsp?page=SeamAuthenticationGuide
- http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3979570
Extended JSF/EL
You can call methods in JSF/EL, and even pass parameters!
(See http://java.sun.com/products/jsp/syntax/2.0/syntaxref207.html#1010522 for the EL syntax)
Seam UI components
See http://docs.jboss.com/seam/latest/reference/en/html/controls.html
The most useful are:
- <s:div> - Ever want to make a div that has the rendered="..." attribute? Well here it is.
Seam Security
Even with the 'simple' security mode Seam provides a very powerful and flexible way to implement security.
- You can use EL expressions in the @Restrict annotation to reference your own security checking components.
- You can use the same EL expressions in the <restrict> element in pages.xml to use your own security checking components on pages.
- Seam comes with built in 'redirect after login' features (i.e. go to the URL the user typed in after logging in).
- Update: Seam 2.1.0 has more "identity management" features including ACL security.
Unit Testing
One of the weakest points in developing web / J2EE applications is that they can be cumbersome to test. Seam provides a built in unit test framework based on TestNG that can simulate JSF lifecycles and interpret EL expressions. Unit tests can be run using the Embedded EJB3 container or Embedded JBoss so you can test everything about the application except the view code.
Transitioning to EJB3/Seam
There are a few things that one needs to unlearn when moving from EJB2.x and something like Struts/JSP to the world of EJB3/Seam.
EJBs as JSF Backing Beans
In Seam you can directly connect the JSF view to EJBs, and you can do it without any XML artifacts. This may seem a bit odd at first, but even if you only use this part of Seam in your application it will significantly reduce the amount of code artifacts you need to make to build a feature.
Here is a simple comparison of the code artifacts required for a basic JSF application:
| Vanilla JSF | Seam and JSF |
Artifacts required:
|
Artifacts required:
|
|---|
Seam removes the need for:
- Separate POJO backing beans - 'form' backing beans can be entities, and the 'controller' can be the a SFSB or SLSB. Intermediate form and controller POJOS are not needed.
- JSF backing bean configuration - The @Name annotation is all that is needed to register Java classes with JSF.
The Seam Interceptor and Stateless Session EJBs
In an EJB2.x application it is not uncommon to have stateless session EJBs that have fields which refer to other stateless components, for example other stateless EJBs or DAOs. With Seam, it is common to make use of fields that are bound to technically stateful objects, for example entities that are in the conversation context. Now, you might ask: "How can a stateless session EJB have fields that are not also stateless?". Good question. The answer is in the way the Seam interceptor handles the contexts.
The Seam interceptor will inject values from the context into the stateless session EJB, invoke the EJB method, then outject any values back into the context. Remember, the context in this case is actually the whole stack of contexts including the conversation context. This allows the 'stateless' EJB object to borrow state from the contexts while it is executing, thereby giving the stateless session EJB pseudo-stateful behavior.
When a stateless EJB is accessed concurrently, the EJB container will provide a pool of stateless session bean instances. The Seam interceptor simply injects the context values into the instance being used for each call.
Things to remember about using fields in statless session EJBs with Seam:
- Fields must be either references to other stateless objects, or seam-injected values.
- References to other stateless session EJBs can be made with the @EJB annotation.
- Fields that are seam-injected with the @In annotation will be 'borrowed' from the contexts every time a method on the bean is invoked.
- Fields that are not injected via @EJB or @In must be completely stateless and have no mutators (i.e. no setter methods), as that would result in strange behavior.
Seam Troubleshooting
My SEAM components are not deploying!
- Make sure the application packaging contains a 'seam.properties' file is in the root directory of the ejb-jar file or files (or the ejb-jar directory if exploded deployment directories are being used). Seam looks of the resource 'seam.properties' in order to find out where to scan for classes with Seam annotations (e.g. @Name).
I've made an @Factory("foo") method, but "foo" is always null!
In the following example there is a factory method for the context variable "foos", but it will not be set (outjected?) into the Seam context. This is because Seam sees the @DataModel field in the EJB has the name "theFoos", and it was looking for a field called "foos" to outject after calling the factory method.
@Stateful
@Name("fooList")
public class FooListBean implements FooList
{
@PersistenceContext
private EntityManager em;
@DataModel
private List<Foo> theFoos;
@Factory("foos")
public void findFoos()
{
Query query = em.createQuery("select f from Foo f");
theFoos = query.getResultList();
}
...
}
Solution: Rename the field to 'foos'. Seam will be able to find the value that was set in the findFoos() method and put it in the Seam context.
I'm using Seam, but I still get LazyInitializationExceptions!
This is most likely because the application is using EntityManagers that are scoped to a CMT transaction. This means that the EntityManager is closed after any EJB method call.
You can solve this in a number of ways:
- If you want to stick with transaction-scoped EntityManagers and don't want to use Session-in-view with Seam:
- Use join fetch in the relevant queries
- Navigate through the object graph to force the objects to load
- Force the objects to load with Hibernate.initialize(obj) (obviously this only works if you are using Hibernate as your ORM).
- Or, if you want to make the leap to Session-in-view with Seam then:
- Use the injected EntityManager managed by Seam in the EJBs/components that supply the data to the view.
- Use the Seam application framework to make queries.
Redirect-after-post doesn't seem to propagate the conversation
Symptoms:
- There is a commandButton or a commandLink that invokes an action method with @Begin on a stateful, conversation scoped bean but the bean gets destroyed before the next page is rendered.
- A new, temporary conversation is generated when transitioning to the next page and a new stateful bean instance is created.
Solutions:
- Don't use redirect-after-post. Remove the <redirect/> tag from the navigation rule in the faces config or in pages.xml.
* OR *
- Enable the redirect filter (it should already be enabled in Seam 1.2.1+) and continue using redirect.
See Seam and redirect-after-post.
JavaScript callbacks are not being executed by Seam Remoting
Symptoms:
- You have some JavaScript that is invoking @WebRemote methods but the JavaScript callback method isn't getting invoked after the server returns the response.
- Seam Remoting JavaScript chokes in Seam.Remoting.processResult because call.callback is not a function.
Solutions:
- Check your component interface for multiple @WebRemote methods with the same name, but different parameters (a.k.a. overloading). JavaScript's idea of overloading isn't like Java, so Seam may have invoked the wrong method. Rename your methods so they are unique, or use nullable parameters.
Seam Tips And Techniques
- Select lists with Seam
- Using Tomahawk Data Table with Seam - http://wiki.jboss.org/wiki/Wiki.jsp?page=DataModelWithTomahawkDataTable

