Notes on JBoss Seam - The Risberg Family

advertisement
Notes on JBoss Seam
Created 02/24/08
Updated 03/05/08, Updated 03/09/08, Updated 05/05/08, Updated 05/12/08, Updated 07/09/08, Updated 07/13/08
Updated 07/22/08, Updated 08/10/08, Updated 08/15/08, Updated 08/19/08, Updated 08/29/08, Updated 09/08/08
Updated 09/26/08, Updated 12/14/08, Updated 01/21/09, Updated 02/02/09, Updated 03/24/09, Updated 03/27/09
Updated 05/09/09, Updated 05/30/09, Updated 06/04/09, Updated 07/27/09, Updated 08/04/09, Updated 08/31/09
Updated 09/20/09, Updated 09/25/09, Updated 10/10/09, Updated 10/29/09, Updated 11/01/09, Updated 11/05/09
Updated 02/28/10, Updated 04/16/10, Updated 05/31/10, Updated 07/17/10
Introduction ...............................................................................................................................................................1
Current Version .........................................................................................................................................................2
Resources ...................................................................................................................................................................2
Seam Unifies J2EE ....................................................................................................................................................3
Concepts of JSF that are Critical to Know and Apply in Seam .................................................................................4
The Seam Lifecycle ...................................................................................................................................................5
The Contextual Component Model............................................................................................................................9
The Seam Component Descriptor ............................................................................................................................ 10
Seam’s Facilities for Dynamic Injection and Outjection ......................................................................................... 11
Component Events ................................................................................................................................................... 13
The Conversation: Seam’s unit of work ................................................................................................................. 14
Understanding Java Persistence ............................................................................................................................... 17
Seam-Managed Persistence and Transactions ......................................................................................................... 18
Using Seam Gen ...................................................................................................................................................... 19
The Seam CRUD Application Framework .............................................................................................................. 20
Using Seam to Create Clickable Data Tables .......................................................................................................... 24
Seam @DataModel Annotation ............................................................................................................................... 25
Validating Input Data .............................................................................................................................................. 25
Workspaces and Concurrent Conversations ............................................................................................................ 27
Bookmarkable Pages ............................................................................................................................................... 29
Securing Seam Applications .................................................................................................................................... 29
Other Topics ............................................................................................................................................................ 30
Seam Testing ........................................................................................................................................................... 31
Seam Page Flow System .......................................................................................................................................... 35
Seam Logging .......................................................................................................................................................... 37
Ajax and JavaScript Remoting ................................................................................................................................ 38
Seam Web Services ................................................................................................................................................. 39
PDF Generation ....................................................................................................................................................... 39
Charting ................................................................................................................................................................... 41
Seam Business Process Management ...................................................................................................................... 42
Seam Drools Integration .......................................................................................................................................... 44
File, Rich Rendering, and Email Support ................................................................................................................ 44
Analysis of the Booking Example Application ....................................................................................................... 45
Appendix A: Seam Libraries and Services ............................................................................................................. 46
Appendix B: Seam Troubleshooting ....................................................................................................................... 47
Appendix C: Performance Optimization when using Seam ................................................................................... 49
Appendix D: Overview of Tutorial Programs Created ........................................................................................... 49
Open Issues .............................................................................................................................................................. 50
Introduction
JBoss Seam is a powerful application framework for building next-generation enterprise applications by integrating
and adding value to JEE 5 technologies such as Enterprise Java Beans 3.0 and JavaServer Faces 1.2. For this reason
alone it is worth learning, as it will save considerable time and aid in building a new set of web applications. Seam
has been designed from the ground up to eliminate complexity at the architecture and the API level. It enables
Page 1 of 50
developers to assemble complex web applications with simple annotated Plain Old Java Objects (POJOs),
componentized UI widgets and very little XML.
EJB 3.0 has changed the notion of EJB components as coarse-grained, heavy-weight objects to EJBs as lightweight
POJOs with fine-grained annotations. In Seam, any class may be a component: Seam it eliminates the distinction
between presentation components and business logic components and brings a uniform component model to the EE
platform.
At the simple level, then, Seam is a way of managing presentation components and their supporting objects. This
improves on JSF, upon which Seam is based. Seam doesn’t introduce many presentation components itself, instead
it focuses on simplifying JEE 5 through shortcuts and facilities.
At the next level, Seam is a facility for managing stateful components. It provides multiple stateful contexts of
different granularity (scopes) from the request, to the conversation, to the business process, thus liberating
developers from the limitation of HTTP sessions. For example, developers can write web applications with multiple
workspaces that behave like a multi-window rich client.
Next, Seam is a collection of related frameworks and integration logic for those frameworks. For instance, there is
integration with Ajax frameworks, integration with RichFaces for advanced UI, integration with iText for PDF,
integration with jPDM for business processes, and more. These extensions bring new functionality into JEE 5.
In other words, learning Seam begins with a knowledge of EJB3 and the JSF components, and then adds in more
and more levels of Seam capabilities. This is what is done through the sample programs discussed here. They in
turn are based on a set of examples from two of the Seam books.
Combined with the other facilities in EJB 3.0 and JSF, Seam can best be thought of as a competitor to Spring. The
biggest difference between these two frameworks is that Spring is stateless while Seam is stateful. It is interesting to
note that the Seam documentation describes that Seam uses “very little XML”, as in Spring we had larger and larger
XML files all the time.
Another very interesting aspect of Seam is Seam Gen, which is a tool for rapidly creating and changing web
applications. Seam Gen can create the persistence facilities for the entities of an application, and the default screens.
It is often compared to Ruby on Rails as a tool for “creating a blogging or photo sharing app in 15 minutes”, but
using the Java platform and JEE 5. This makes it very handy for mockups and prototypes.
Current Version
The current version of Seam is 2.1.2.GA, released on June 8, 2009. The download is about 136MB, which includes
RichFaces, JSF, Trinidad (a set of JSF components), Hibernate, Drools, FreeMarker, JBoss Embedded, and
JFreeChart. There was a prior version 2.0.2.SP1, released in May 2008. The version before that was Seam 2.0.1,
released in early 2008. Several of the third-party books are really about Seam 1.2 or earlier, and this version is still
available.
We switched to Seam 2.1.2.GA in early April 2010.
Resources
The download includes a 500-page PDF reference manual on Seam, which has chapters for the basic component
model and examples, then moving on to business processes, iText, etc. The download contains about a dozen
example applications. These are described in the reference manual. One application is a blogging application,
which was interesting to try out, though the most important applications for us were those which focus on
conversational interactions.
“Seam in Action” by Dan Allen. Manning Press, August 2008, 624 pages. List price $49.99, Amazon price $29.69,
used from $25.33. Rated 5 stars on Amazon.com. Considered the best overall book on Seam. It is as well-written
Page 2 of 50
as most other Manning books, and has good examples. The author was on several of the Seam committees, and has
written several articles on Seam. We bought a copy in March 2009.
“JBoss Seam: Simplicity and Power Beyond Java EE” by Michael Juntao Yuan and Thomas Heute. Prentice-Hall,
April 2007, 432 pages. List price $39.99, Amazon price $29.45, used from $20.80. Rated 4 stars on Amazon.com.
Some portions of this book are a sales pitch, some parts are a cookbook or tutorial, some seem to be notes that the
product manager maintained. Some parts are based on the downloadable reference manual. However, despite the
poor organization, the examples are useful, plus the areas covered are more comprehensive than other books
available in 2008. It was one of the first books on Seam. We bought a copy in May 2008. The second edition came
out in February 2009.
“Practical JBoss Seam Projects” by Jim Farley. APress, July 2007, 229 pages. List price $39.99, Amazon price
$29.99, used from $19.99. Rated 4.5 stars on Amazon.com. Not a long book, but has a good overview, and is
organized into a useful sequence of learning steps. It is written for Seam 1.2, but it makes up for this by having
useful projects. We bought a copy in December 2008.
“Beginning JBoss Seam: from Novice to Professional” by Joseph Faisal Nusairat. APress, February 2007, 376
pages. List price $39.99, Amazon price $29.99, used from $8.99. Rated 3 stars. Glanced through this in the
bookstore, but should reread it. Unfortunately it is for an out of date copy of Seam.
“Java Persistence with Hibernate” by Christian Bauer and Gavin King. Manning Press, November 2006, 704 pages,
$49.99. Amazon price $32.99, used from $28.44. Has a chapter on Seam at the end, though it covers mostly the
JSF integration and data persistence aspects, and concepts such as conversations. The Seam version described is out
of date.
There is a three-part article by Dan Allen on Seam at http://www-128.ibm.com/developerworks/java/library/jseam1/index.html, http://www-128.ibm.com/developerworks/java/library/j-seam2/index.html, and
http://www.ibm.com/developerworks/java/library/j-seam3/index.html. This material is a prior version of his “Seam
in Action” book.
The web site with product information from the JBoss Group is at http://www.jboss.org/products/seam.
The web site for the developer’s community is at http://seamframework.org.
Seam Unifies J2EE
Seam is a framework that uses EJB 3.0 concepts, such as annotations, to configure and simplify web applications.
Seam makes it easy to accomplish tasks that were “difficult” with JSF. For instance it provides a number of JSF
component tags and annotations that increase the “web friendliness” and web page efficiency of JSF applications. It
expands the EJB3 component model to POJO’s (meaning the use of annotations to describe how these objects are
managed).
Page 3 of 50
The idea of backing beans is replaced with stateful session beans. Most enterprise application frameworks tend to
focus on stateless behavior, but Seam reverses this to focus on stateful interactions and keeping sessions open. Web
applications are inherently multi-user applications and e-commerce applications are inherently stateful and
transactional.
Seam was designed from the ground up to promote Object Relational Mapping best practices. With Seam, there are
no more DTO’s to write, lazy loading just works, and ORM performance can be greatly improved because the
extended persistence context acts as a natural cache to reduce database round trips.
Also like Spring, Seam provides a container environment that is designed for easy test code generation and run-time
testing. You can swap components in and out, and use mock objects. This is largely because the components don’t
set up their own references (which would be hardcoded to the real objects), but the container does this (allowing use
of the mock objects). In the Seam testing framework, you don’t need to start up the application server just for
running a test.
Finally, there are an increasing set of tools for using Seam, including Seam Gen, which will create Seam
applications quickly.
Concepts of JSF that are Critical to Know and Apply in Seam
Backing Beans and their counterpart in Seam
Backing beans are a critical concept in JSF, as they are the Java that supports the presentation of content by the
components in the JSF file. This is quite similar to Wicket, in which the page file defines components declaratively,
and the components refer to Java objects (by id) that implement the procedural code. However, the analogy is not a
Page 4 of 50
strong one (at the JSF level), because the JSF backing beans are much harder to configure and link than in Wicket,
and this is improved on in Seam.
Components
The large set of JSF components available are commonly used in Seam. However, several are available with
extended capabilities:



For instance, the data table supports AJAX-based scrolling and paging
There a number of facilities to support JavaScript on the client side
There is integration of AJAX frameworks such as prototype or dojo.
The Expression Language
The JSTL expression language is used throughout Seam, just as it is with JSF. For instance, to display a field from
an object, you would write:
<h:outputText value=”#{orderManager.trade.symbol}” />
This would be looking for a getter for “symbol” on the trade object, and using BeanUtils (with reflection
underneath) to find it and call it. Hence, JSF is all about beans and their getters and setters.
As mentioned earlier, there are some Seam-specific EL enhancements. An example is the ability to call functions
with arguments. To use it, just put your arguments inside parentheses:
<h:commandButton value=”Submit” action=”#{myinstance.save(‘name’, address)}” />
In this example, name is a String literal and address is a ValueExpression.
Hence, Seam extends the integration from being about getters and setters to being about any method, including those
with arguments. If the method has no arguments, you can call it using either “#{myinstance.methodName()}”
or “#{myinstance.methodName}”. Both have the same effect.
Integration with JSF Data Tables
Seam allows you to specify a @DataModel to be used, which will be injected and outjected (these concepts are
define below). Seam also allows you to create a @Factory method that creates the data model and gives it a name.
Seam also provides an easy facility to track what object is selected in the table.
The Seam Lifecycle
Exploring how Seam participates in a Request
Section 3.1 of the Allen book describes the inner working of the Seam request processor, and its relationship to the
servlet at the very bottom, and the Facelets facility in the middle.
An analogy that appears in Dan Allen’s earlier writing is that a framework like Struts “pushes” information toward
the JSP, while the JSF-based component framework is actually driven by the components and their “pulling” of
information from the application data, and using it to make rendering decisions.
Before getting into configurations, it is important to define the phrase life cycle, as it is being used quite casually.
There is a servlet context life cycle, a request life cycle, a JSF life cycle, and a Seam life cycle. Let’s sort them out:

The servlet context life cycle represents the entire lifespan of the web application. It is used to bootstrap
services, such as the Seam container.
Page 5 of 50

The request life cycle, on the other hand, is the overarching life cycle for a single request. It envelops the JSF
and Seam life cycles. It lasts from the time the browser requests a URL handled by the server to the end of the
response generation.
This chapter also includes a discussion of benefits of Facelets vs. JSP for the rendering framework. Facelets is more
than a view parser, it provides a facility to manage the display components in a more useful way. In addition, its
template facility, like the one in Struts, is a critical piece of generating pages with common elements such as headers
and footers. See our document “Notes on Facelets” for more information on the Facelets tag set.
One area of specific improvement is the <s:decorate> tag that can be used to create combination of a label and an
input field with a simple specification. Another is the <s:div> tag that is like a <div> except that it supports the
render attribute to control visibility.
Finally, the Seam filter provides a facility to serve up resources such as CSS and others in a way that is similar to
that used in Wicket.
Review of the JSF request life cycle
Here is a brief review, based on our documents on JSF. The stages are as follows:
JSF can handle two types of requests:


An initial request – this corresponds to the non-P methods in the Incra framework, i.e., the methods that simply
render information in a form, ready to generate submit. There is no validation. It matches the line called “no
query data” in the above figure.
A postback – this corresponds to one of the P-methods in the Incra framework, i.e., the methods that are
processing a post. The steps include performing validation, updating information in the application, and
sending a confirmation response back, which might include a redirect to somewhere else.
We haven’t seen these terms used elsewhere.
It’s certainly possible to learn how to develop a JSF application while remaining naïve of the fact that there’s an
underlying life cycle that processes each request. The diagram below shows the leap the JSF designers want you to
Page 6 of 50
make between the click of a command button (e.g., <h:commandButton>) and the invocation of an action method
on a server-side component that’s registered with the command button using an EL method binding expression.
This event-driven relationship is one of the ways that JSF is intended to make web development easy. The direct
binding between the command button and the server-side component weeds out most, if not all, of the low-level
details of the HTTP request that you would otherwise have to address, instead getting you right down to the business
logic. There is no HttpServletRequest, HttpServletResponse, or ActionForm (for ex-Struts
developers) to have to concern yourself with.
However, the reality is that you must define the relationship between the page contents and the backing bean, which
is done through a configuration file, and then you must define the relationship between the backing bean and the
EJB component. Seam improves on all of this.
Seam’s page-oriented life-cycle additives
While JSF is based around the idea of pages, the dispatching model is rather simple: you display a page, it pulls the
information for the page from the components, and it is done.
Seam adds a page descriptor that can specify a good bit more information about the page and hence what happens
when the page is referred to, fetched, displayed, etc. This information is located in the pages.xml file. The page
descriptor can specify:











Define contextual navigation rules
Invoke actions before rendering a view
Enforce security restrictions and other prerequisites
Generate messages and pass parameters on a redirect
Control conversation boundaries
Control page flow boundaries
Control business process and task boundaries
Map request parameters to EL value bindings
Bind context variables to EL value bindings and vice versa
Raise events
Handle exceptions
If desired, the page specifications can be moved into individual files that are named <viewed>.page.xml. For
instance, the page file for Organization.xhtml is Organization.page.xml. This is easier to maintain for a large
development team. Note that you cannot have the page information in both places.
This descriptor is a stand-in for navigation rules which in JSF used to be placed in faces-config.xml. The main
difference that <navigation-rule> becomes <navigation>, and <navigation-case> becomes <rule>.
Page parameters
These are more important than we first realized. Page parameters are passed as human-readable request parameters.
This is the first place where the pages.xml file comes into play.
Seam lets us provide a value binding that maps a named request parameter to an attribute of a model object.
<pages>
<page view-id="/hello.xhtml" action="#{helloWorld.sayHello}">
Page 7 of 50
<param name="firstName" value="#{person.firstName}"/>
<param name="lastName" value="#{person.lastName}"/>
</page>
<pages>
When the page is processed, the params are processed first. This means before any actions (described below).
However, for some reason, most of the example pages.xml files that we have seen have them located last.
The <param> declaration is bidirectional, just like a value binding for a JSF input. For instance, if we have a form
on a prior page that submits, this declaration will move information into the model attributes (such as
person.firstName) in the above example. Also for instance, if we wish to refer to a model attribute value in a page
(such as in a EL expression on the page, the specified model attribute will be available at the given name).
The essential idea behind all this is that however we get from any other page to /hello.xhtml (or from
/hello.xhtml back to /hello.xhtml), the value of the model attribute referred to in the value binding is
"remembered", without the need for a conversation (or other server-side state).
Using page actions
The page action facility is a major improvement on any JSF counterpart.
The file defines the actions that can occur in the page, and the pre-checking and post-checking that is to be carried
out, Seam’s page actions can be combined with its intelligent navigation capabilities in order to make decisions
about how to direct the user in the event that a page action needs to divert the user from the requested page.
There are a set of built-in page actions that correspond to security-checking access to a page, and also defining error
condition handling.
Navigation
Navigation facilities include:







Use an arbitrary value binding to determine the outcome of an action rather than using the return value of
the action method
Make navigation cases conditional using a value-binding expression
Indicate how the conversation should be propagated through the transition
Control page flows and business processes through the transition
Add JSF messages before rendering or redirecting
Add parameters to a redirect
Raise an event at a transition
For instance, here is an example:
<page view-id="/FacilityEdit.xhtml">
<navigation from-action="#{facilityHome.persist}">
<rule if-outcome="persisted"
if="#{facilityHome.enterActivity}">
<redirect view-id="/ActivityEdit.xhtml"/>
<param name="activityFrom" value="Activity"/>
<message severity="INFO">
Enter activity information for #{facilityHome.instance.name}.
</message>
</redirect>
</rule>
<rule if-outcome="persisted" if="#{!facilityHome.enterActivity}">
<redirect view-id="/Facility.xhtml"/>
</rule>
</navigation>
Page 8 of 50
</page>
This indicates that when leaving the FacilityEdit page, we try to persist the activity, and if that works, we try to
record another activity.
It is also possible for the actions to return the page to jump to, rather than a string that is used to control the
dispatching in JSF. This cuts down on one more level of indirection that would need to be specified.
Finally, Seam supplies some additional UI components, such as <s:button> and <s:commandLink> that work
with this information. In most respects, they are similar to their JSF counterparts, however, they also supply
parameter values to control propagation of the conversation id, which is described below.
Looking at the Full Request Life Cycle when using Seam
The JSF life cycle under the direction of Seam is more well-balanced than its intrinsic counterpart. For instance, the
initial request processing is just as full-featured as the postback processing. This is because Seam expands the
activity in the initial request by applying features described through the page configuration. These new features
include parameter mappings, front controllers, and request routing.
The Allen book gives a table (pages 123-124) of 22 different steps in the processing of a request with Seam, of
which only 3-4 correspond to JSF steps. These steps include transaction management (if configured in) as well as a
number of error recovery checks.
A try-catch block around the life cycle
The ability to handle exceptions is just as important as all the other cool and exciting things that a framework such
as Seam can do. Unfortunately, exception handling is often overlooked. This is true of JSF. The faces-config.xml
descriptor doesn’t allow exception handlers to be defined. Fortunately, Seam taps into the JSF life cycle to trap and
handle exceptions gracefully.
The Contextual Component Model
At its core, Seam is best understood as a facility for managing contextual components that are stateful. The tools
available to manage such components are similar to Spring’s, such as Dependency Injection and Beans, but are
carried out in a set of run-time stateful contexts that have different scopes and lifecycles.
These scopes include: Event, Session, Application, etc. Any POJO can be marked as being a stateful component,
including those which hold business logic and those which hold entity content. There is even a long-running scope
that is useful for business processes.
The Injection facility is stronger than Spring’s, as it includes outjection as well as injection. Hence, while the Spring
model is focused on injection of dependencies at run-time initialization, Seam continues this past the initialization
steps through the runtime. Seam avoids XML abuse by relying on annotations for the specification of dependencies
and runtime state. Of course, XML is still available, and this not entirely bad for configuration data. Much of the
deployment-specific configuration should continue to go into XML configuration files.
Also, the Seam facility for managing components and their lifecycle and dependencies is based on annotations,
rather than an XML file such as applicationContext.xml.
Contexts
While components tend to be set up initialization time through a scanning of the class files and initialization of the
classes marked as components, Seam extends upon this to provide run-time support for contexts.
Seam contexts are created and destroyed by the framework. The application does not control context demarcation
via explicit Java API calls. Contexts are usually implicit. In some cases, however, contexts are demarcated via
annotations.
Page 9 of 50
Most components have default contexts, such as Application, Conversation. No component has a default context of
Session.
The Seam Component Descriptor
It is possible to define Seam component attributes through XML files, but this is to be avoided. There are only a
small set of cases in which component descriptors are needed:
The structure of a component descriptor file is similar to the applicationContent.xml file in Spring. Instead of
<beans> use <components>, and instead of <bean> use <component>.
There is a similar approach to organizing the attribute of the <component> elements. Here is an example:
<components xmlns="http://jboss.com/products/seam/components"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://jboss.com/products/seam/components
Page 10 of 50
http://jboss.com/products/seam/components-2.0.xsd">
<component name="newSalesOrder"
class="com.incra.module.salesOrder.action.NewSalesOrder" scope="event"/>
<component name="passwordBean"
class="com.incra.module.user.model.PasswordBean" scope="event"
auto-create="true"/>
</components>
Wiring of Components
Developers with Spring experience might be tempted to use component specifications to inject dependencies into the
POJO’s. Instead, you should use Seam’s dynamic dependency injection, which is based on the @In annotations.
However, see the notes below regarding how to not over-use @In-based injection.
Suggestions
The main place to use component descriptions is for the following reasons:



Configure Seam runtime settings — Seam has a lot of switches and levers that you can use to control how it
functions. To cite a couple of examples, you can enable debug mode, disable transaction management,
define the authentication method, customize parameter names used to manage conversations and the
conversation timeout period, specify the names of the resource bundles, or configure the available themes.
These components act as the central switchboard in Seam.
Activate a feature that is disabled by default — Some of the built-in components aren’t useful to all
applications (or may depend on an environment that isn’t always available). Seam disables these
components by default. The component descriptor gives you an opportunity to enable them. To provide
some examples, you can enable jBPM, hook into the email service, or start the Spring container adapter.
Customize a component template — Seam provides a number of component templates. These are cookiecutter components that you can customize for your own application domain. Examples include the
EntityManagerFactory and managed persistence context (and Hibernate equivalents), a Seam
Application Framework object (Query, Home, and Controller), a JMS topic publisher or message sender, or
a Drools rules manager. These classes don’t bear the @Name annotation and therefore aren’t components
until you strike them into action by configuring them in the component descriptor.
Although seam-gen places the components.xml file in the WEB-INF directory, consider storing it in the META-INF
directory instead, where it’s accessible to unit and integration test environments that don’t recognize the WEB-INF
directory as part of the classpath.
Seam’s Facilities for Dynamic Injection and Outjection
There are several aspects of Seam in which it provides a container for components that builds on the EJB 3 model,
and also integrates more concepts from IOC-based frameworks such as Spring. Components are stateful objects,
usually EJBs, and an instance of a component is associated with a context, and given a name in that context.
Bijection provides a mechanism for aliasing internal component names (instance variables) to contextual names,
allowing component trees to be dynamically assembled, and reassembled by Seam.
This idea of dynamic injection is quite powerful. For one thing it simplifies the amount of code in the manager level
objects that look up related objects. This could be about 10-20% of the body of each method. In 2003-2006
versions of the Incra code, this got moved into the init() methods of most of the action classes, and was located on
the superclass of groups of related actions, but in Seam, you just specify @In and avoid the explicit lookup calls.

Components can have dependencies injected. These use the following tags:
o @In – a component is injected from the context before processing each request. There is also an
option to create the component if it doesn’t yet exist.
o @Out – the value is updated back into the context after processing each request
Page 11 of 50

Components can be managed by global variables that, for instance, provide access to all current
conversations.
Lifecycle Annotations
The following annotations are key to controlling lifecycle of a component.
@Create
Specifies that the method should be called when an instance of the component is instantiated by Seam. Note that
create methods are only supported for JavaBeans and stateful session beans. Note that there can be only one
@Create method (there cannot be one per level of class inheritance).
@Destroy
Specifies that the method should be called when the context ends and its context variables are destroyed. Note that
create methods are only supported for JavaBeans and stateful session beans.
Destroy methods should be used only for cleanup. Seam catches, logs, and swallows any exception that propagates
out of a destroy method.
@Remove
This is part of J2EE, not Seam
Use the @javax.ejb.Remove annotation to denote a remove method of a stateful session bean.
When the method completes, the EJB container will invoke the method annotated with the
@javax.annotation.PreDestroy annotation, if any, and then destroy the stateful session bean.
Note that all stateful session bean components must define a method annotated @Destroy @Remove in order to
guarantee destruction of the stateful bean when its containing context ends.
Bypassing Bijection
As established earlier, bijection is implemented as a method interceptor. Method interceptors are applied around
method calls that are invoked on proxy objects. When you ask the Seam container for a component instance—
perhaps through an EL expression or an injection—what you get back is a proxy of the instance. Therefore, any
method call invoked on that proxy is going to pass through the method interceptors and, in turn, trigger bijection.
However, method interceptors are blind to what goes on within the target method. As far as the interceptor is
concerned, the target method is a black box.
Inside of the intercepted method, you’re dealing with the raw instance of the component when you refer to the
implicit variable this. Local method calls (i.e., methods on the same class) aren’t observed by the method
interceptors, and therefore, bijection isn’t wrapped around them. If you have a strong grasp of how method
interceptors work, this fact should come as no surprise to you. However, for those with less exposure to method
interceptors, the distinction between the two circumstances may not be so obvious.
Since bijection is provided by a method interceptor, you can avert bijection by disabling the interceptors on a single
method or on the entire component. You instruct Seam not to apply interceptors by adding the
@BypassInterceptors annotation, at the class or method level. The method-level annotation is a good way to
optimize one area of the code without cutting out the benefits of interceptors from the component as a whole.
What doesn’t work is to bypass injection by avoiding calling the getter/setter methods on the injected objects. In
other words, don’t make the attributes public and skip the getter/setters. The reason is implied in the above
discussion which states that the result of an injection is a proxy for the object, rather than the actual object. We
found that breaking this rule caused us to fetch null.
Page 12 of 50
Another implication of the proxies is that you shouldn’t store them into local instance variables, as they are
temporary.
Factory Components
These are components that, like those in Spring, don’t return the specified object when accessed by name, but return
an objected by the specified object.
Factory and manager components work together to set up complex state.
We have not used this very much, except in the persistence factory facilities. It is also used in the @DataModel
construct.
Other Lifecycle attributes on components
@Role
As you know, a component must be assigned a name. But that doesn’t mean that it can’s be assigned more than one
name. After name and scope combination are specified through @Role annotation.
@Startup
This annotation causes Seam to create the component at application startup, and this is often used for initialization
components. It is probably easier to use this annotation than developer any other facility for performing this
function.
Component Events
Dynamic injection helps decouple components because it eliminates explicit lookups for dependent objects.
However, the components still interact with one another directly. This arrangement works well when the
components are all working to accomplish a common goal, as is the case with the registration example. However, in
cases where tangential logic must be performed, perhaps even to spawn an asynchronous operation, events may be a
better option. Events offer a way for components to pass messages to one another. They provide separation of
concerns, make components easier to test in isolation, and can even remove a hard dependency on an API such as
JSF.
Events can be raised by a component or generated during any page-related activity. These events are passed through
the Seam container, which acts as the messaging mediator. Seam’s event support works much like a messaging
service such as JMS.
Specification of Events
There are both producers and consumers. When an event is raised, it’s posted to the Seam container. Seam then
looks for registered observers for that event and notifies them by executing the registered methods.
Events can be raised from within a Seam component either using the Seam Events API—the built-in Events
component—or using an annotation. The Events API offers the most flexibility, but it does tie your code to that API.
The annotation @RaiseEvent, on the other hand, allows you to control event creation declaratively.
You can also raise events programmatically, as in:
public String register() {
...
entityManager.persist(newGolfer);
Events.instance().raiseEvent("golferRegistered");
...
return "success";
}
Page 13 of 50
Let’s observe the golferRegistered event. Instead of going through the exercise of setting up an entity and
database table, we just throw in some logging statements:
@Name("registrationBookkeeper")
@Scope(ScopeType.APPLICATION)
public class RegistrationBookKeeper {
@Logger private Log log;
private int cnt = 0;
@Observer("golferRegistered")
synchronized public void record(Golfer golfer) {
cnt++;
log.info("Golfer registered – username: " + golfer.getUsername());
log.info(cnt + " golfers have registered since the last restart");
}
}
Since the record() method is a component method, it will trigger bijection, which can be useful for injecting the
EntityManager when you build the real implementation. You can also register the observer using the component
descriptor. The latter is useful if you can’t add the @Observer annotation to the class—perhaps because it can’t be
modified—or to have non-Seam components observe events. To do so, you’d add the following declaration in the
component descriptor:
<event type="golferRegistered">
<action execute="#{registrationBookkeeper.record(newGolfer)}"/>
</event>
This is quite interesting, not because it is unique (which it isn’t), but it is very similar to the event management
within JMS. You can publish on a name, and subscribe on a name. We must have built similar frameworks several
times over the last ten years, and here is it available and supported by someone else.
The Conversation: Seam’s unit of work
Now that we have defined the various scopes of a context, let’s focus on the most interesting one: conversational. A
conversation is a set of data interchanges that exist across multiple web page requests and submits.
In real life, we handle multiple conversations all the time. The best example in the technical world is probably
multi-threaded message boards. Within an application, you must typically create specific support for conversations
and management of conversations if you want to support them. This can be a large amount of code, but this is built
into Seam.
By default (i.e., if you omit the @Scope annotation on the component class), a Seam stateful component has a
conversation scope, but the conversation spans only two pages: the page submitting the request, and the page
generating the response. Consider the following stateful session bean:
@Stateful
@Name(“manager”)
@Scope(SESSION)
public class ManagerAction implements Manager {
@In @Out
private Person person;
private String msg;
@PersistanceContext(type=EXTENDED)
private EntityManager em;
public String sayHello() {
// save person
Page 14 of 50
// update msg
}
@Remove @Destroy
public void destroy() { }
public String getMsg() { return msg; }
public void getMsg(String msg) { this.msg = msg; }
}
When the user submits the form, the ManagerAction object is instantiated with user input captured in its person
property. The ManagerAction object stays valid after the sayHello() method exists so that the msg property can
propagate back to the response page. In addition, we gave the EntityManager an EXTENDED type, which allows it
to lazy load more data from the database as needed when the sayHello() method exits.
In JSF, you can choose to redirect the response page to its own URL instead of using the request page’s URL. With
the Seam Filter, Seam conversation components can live until the redirect page is fully rendered.
Long-Running Conversations
To make the conversation have a longer scope, we must add some additional annotations. There are specific
annotations that indicate that a piece of business logic begins, ends, or is part of a conversation.
Use the @Begin annotation to start a conversation. When this invoked, Seam creates a bean instance and a new
conversation context associated with it. The join=true attribute tells Seam to merge two conversations if find() is
invoked from inside a conversation. Otherwise, an exception is thrown when you call a @Begin method from inside
a conversation.
Use the @End annotation to end a conversation. Seam destroys the stateful session bean and cleans up any loose
ends. All possible methods to exit the conversation should be tagged with @End.
@Stateful
@Name(“hotelBooking”)
@Scope(CONVERSATION)
@LoggedIn
public class HotelBookingAction implements HotelBooking, Serializable {
@Begin(join=”true”)
public String find() {
// initialize the conversation state
}
@End
public String confirm() {
// save data and end the conversation
}
}
There are several subtle shifts that have occurred since the stateful “hello world” program shown earlier. First of all,
the action/manager that lists the created entities (in this case the bookings) is now separate from the action/manager
creates a new entity (a booking). The BookingsListAction has session scope, and the BookingAction has
conversational scope. (The only reason why the list action has session scope instead of application scope is that it
also maintains the state of selection flags on the bookings list).
Another subtle point is that the entity being used for persistence (such as Booking, in this case), must have a scope is
that is also Conversational. Since this is the default, this is easy to do.
Page 15 of 50
Another shift is that it is not clear when the class constructor is called for the BookingAction bean, but we know that
the find() method on the bean will cause all of the other setup code to run for this conversation, getting us a unique
bean instance. We know that there must have been a non-unique bean instance, since we call find() on it, as:
<h:commandButton value=”Start Booking by Finding Hotels”
action=”#{hotelBooking.find}” />
Another shift is that the bean with conversation scope must implement serializable. This appears to be so that Seam
can persist these objects to memory, particularly if they are very long-running conversations.
Controlling Conversations
Add the table of conversion control annotations here
You can also control the scope of conversations using directive in the pages.xml file(s).
Links and Buttons
If the user clicks on a regular link the middle of a conversation, the browser issues a simple HTTP GET request, and
the current conversation context is lost. Seam then starts a new conversation, but what if we wanted to stay in the
same conversation?
To solve this Seam provides two tags, s:link and s:button, which augment their corresponding JSF counterparts to
keep the result of the click inside the conversation. To use either of these, define the <s:> namespace as:
<html xmlns=”http://www.w3.org/1999/xhtml”
xmlns:h=”http://java.sun.com/jsf/html”
xmlhs:f=”http://java.sun.com/jsf/core”
xmlns:s=”http://jboss.com/products/seam/taglib” >
and here are some examples of using s:link:
<s:link view-id=”/login.xhtml”
value=”Login” />
<s:link action=”#{login.logout}” value=”Logout” />
The s:link tag also has a propagation control attribute that allows you to also force the beginning or ending of the
current conversation.
If you want to use an h:commandButton tag (for some historical or JSF reason) tag, have it contain a
s:conversationPropagation tag, as shown below:
Page 16 of 50
<h:commandButton action=”main” value=”Abandon Session”>
<s:conversationPropagation type=“none” />
</h:commandButton>
It is not yet clear to us if this example causes the conversation to be exited or ended cleanly. Check further.
Configuring Conversations
You can set the global conversation timeout in the components.xml configuration file. The unit of measure is
milliseconds.
<components>
<core:manager conversation-timeout=”120000” />
</components>
You can also specify a timeout for each individual conversation in the pages.xml configuration file which is used in
business processes (this will be described in more detail below).
Based on earlier discussion, an unclosed conversation does appear to create a possible memory leak. But we have
found that Seam does a better job than manually managing the session anyway, and there is also a facility to review
pending conversations and resume or destroy them.
Understanding Java Persistence
Java persistence is the mechanism by which object-based entities are translated between the Java runtime
environment and a relational database. It’s undoubtedly the most popular feature of the Java EE platform, perhaps
even the Java language. This popularity can be attributed to the fact that persisting data is central to nearly all
enterprise applications. For that reason, persistence is a core part of Seam. In fact, you can’t get very deep into a
Seam application without encountering it
JPA is implemented (at least in the case of JBoss), as a layer on top of Hibernate.
You can support entities and relationships by annotating them. This is covered best in the EJB 3.0 documentation.
See our document “Notes on EJB 3.0 and JBoss”.
Persistence Units and the Persistence Manager
The persistence unit groups the entities to be managed and determines how they are to be associated with a database
runtime. It also indicates which transaction type is to be used when the database operations occur. The persistence
unit consists of three main parts:



Entity metadata—A set of all annotated classes or XML mappings to be managed, containing instructions
for how Java classes and bean properties are mapped to relational database tables. It also indicates the
relationships between entities and defines the global fetching strategy used to traverse relationships.
Persistence unit descriptor—Specifies which persistence provider to use (not applicable for native
Hibernate), database connection information, transaction type and lookup, and vendor extensions.
Persistence manager factory—The runtime object representing the configuration of the persistent unit as a
whole. The factory is used to create individual persistence managers that provide the services for managing
entity instances.
The persistence manager is the counterpart to the Hibernate Session object.
It’s important to understand the distinction between application-managed and container- managed persistence
managers. The former is where the application bootstraps the persistence unit and is responsible for creating its own
persistence managers. The latter, which only applies to JPA, is where the container loads the persistence unit and
dishes out persistence managers as requested. Regardless of which style of Java persistence you’re using, you must
first set up a persistence unit.
Page 17 of 50
Transactions
As indicated in the EJB3 documentation, persistence operations are typically carried out within a transaction.
The transaction has several benefits:



Support for rollbacks
Bounding of context changes
Efficiency, in that database synchronization typically occurs only at the end of a transaction (unless explicit
flushes are used)
However, transaction and persistence context management is not cleanly supported in regular EJB3. For instance,
the servlet environment, an abstraction over the HTTP protocol, is a less-than-ideal setting for performing
transactional data processing. The lack of continuity between the stateless HTTP requests means that database
connections and persistence managers are constantly being turned over. To further disrupt continuity, a web
application is typically partitioned into layers, relying on a data layer to perform Java persistence operations, and
then shut down connections afterwards. When a persistence manager is closed, the entities it manages become
detached and no longer support lazy loading (at least they shouldn’t) or automatic dirty checking, two valuable
features of ORM.
Instead, Seam uses the concept of “conversations” as described above to manage the transaction boundaries and
their effects.
Comparing Hibernate and JPA
Hibernate has been around a lot longer than the JPA specification and has the advantage of being a self-directing
open source project, not held back by the (sometimes very slow) Java Community Process ( JCP). JPA, on the other
hand, has the advantage of leveraging the standard Java EE environment. While that word standard carries a great
significance, you’re always going to get more features using the Hibernate APIs.
The most important feature, and the one that the Hibernate developers felt should have been in JPA from the start, is
manual flushing of the persistence context. This feature allows you to defer updates to the database until an explicit
flush is issued, such as when the use case ends. Manual flushing is essential to implementing an application
transaction (called an atomic conversation when managed in the context of a Seam conversation).
Other strengths of Hibernate include Hibernate Search, a recent extension that supports full-text searching using the
Lucene search engine. There’s also an extensive set of association mappings that Hibernate supports over JPA, such
as indexed collections. Hibernate can also save keystrokes by allowing you to use shorthand for JPQL in the style of
Hibernate’s HQL (e.g., “from Course” instead of “select c from Course c”) and generally has a more intelligent
query parser.
Hibernate also offers a set of objects to build a query using a Criterion API, which we have used extensively in
projects to build reporting tools. The counterpart using JPA is to build a complex query string.
Seam-Managed Persistence and Transactions
In a Seam application, we typically assemble and modify database entity objects throughout a conversation, and then
commit at the end.
Persistence Context Management
To realize the true value of Java persistence, the persistence manager—a general term for a JPA EntityManager
or Hibernate Session—must be scoped properly. Earlier, we discussed that if you treat the persistence manager as
a stateful component, it can do a lot for you; if you don’t, it can lead to a lot of pain. The transaction scoped
persistence context inhibits the capabilities of Java persistence and is generally discouraged in Seam.
The challenge of using an extended persistence context is deciding how long to extend it without overdoing it. If it’s
not held open long enough, your entities become detached prematurely. If it’s held open for too long, it can result in
Page 18 of 50
an overzealous cache and memory leaks. As it turns out, the persistence manager was intended to serve a use case,
making the conversation context the ideal host for an extended persistence context.
Drilling down to Hibernate
This is really a note for the EJB3 developer’s notes document, but it appears in the Seam documentation. If you are
using Hibernate underneath your JPA implementation (such as in JBoss), you can access the Hibernate Session
using the following:
Session session = (Session) entityManager.getDelegate();
You could also define a factory in Seam to hide the cast:
<factory name=”hibernateSession” value=”#{entityManager.delegate}”
auto-create=”true” />
This allows you to use the annotation:
@In private Session hibernateSession;
Setting up a Persistence Unit
This is done through a component definition in the XML file. Use
<persistence:entity-manager-factory name=“entityManagerFactory”
persistence-unit-name=”open18” />
Transactions
Transactions are enabled by default for all EJB3 session bean methods in a Seam application.
You can force a transaction rollback if certain conditions in your application are not as serious as an exception, but
you still want to roll back for business reasons. Use the @Rollback annotation, such as:
@Rollback(ifOutcome={“failure”, “not-valid”})
public String confirm() {
…
}
After the transaction is rolled back, JSF displays the navigation target page associated with the return string value,
which could well be your error page.
Atomic Conversation (Web Transaction)
If you use a Seam-managed EntityManager, setting the FlushMode to MANUAL stops the transaction manager from
writing any updates to the database until the end of the transaction.
Another alternative is to disable the transaction manager on all methods except for the @End method. Because this
approach requires method-level transaction demarcation, it can be used only on EJB3-managed EntityManager
objects. Mark the methods as @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED).
Using Seam Gen
Seam Gen is a utility that can be run from the command line or interactively using Seam Tools, which is part of
JBoss Tools. In this document, we describe the command-line based approach. The other approach is covered in
our document “Notes on JBoss Tools”.
Run this from the home directory of Seam. First, set up project parameters for the generator: seam setup
Page 19 of 50
Create the project skeleton (i.e., directories, library trees, and build files): seam create-project
Generate the entities and their screens by using reverse engineering of database content: seam generate
Create an action: seam new-action. This takes arguments such as:
Seam component name: registerAction
Local interface name: RegisterAction
Bean class name: RegisterActionBean
Action method name: register
Page name: register
This command generates code skeleton and the test skeleton.
The structure of the generated application includes:
(within src/model are the Entity definitions)
The Seam CRUD Application Framework
The Seam CRUD Application Framework is an organization of classes that covers all aspects of CRUD operations
as well as editing screens for the objects. It includes skeleton versions of persistence management, business logic
managers, and more. The Application Framework is used by all of the code generated using Seam Gen. Hence,
whether you use it or develop your own, it is worth studying as an example.
Without Seam, a plain JSF application has at least four layers: the UI page, the backing beans for the page data and
the event handlers, the session beans for the business and data access logic, and the entity beans for the data model.
Page 20 of 50
Seam has eliminated the artificial gap between the JSF backing beans and EJB3 session beans. But in addition,
Seam comes with a built-in framework for CRUD operations. The Seam application framework essentially provides
prepackaged Data Access Objects (DAO’s), which are called “Homes”.
Concepts
The Entity Home classes are like the DAO classes in our prior work, as they package the persistence manager. Each
home is per-class. A Home manages an entity instance by caching it and coordinating CRUD operations on it with
the persistence manager, all completely transparent to the entity instance. Each Home is represented by the Home
class, which extends from PersistenceController, or any subclass of Home. The framework classes, such as
Home, are abstract classes that are, in reality, just component templates. They are also agnostic of the persistence
framework. Seam provides two implementations of Home: one for JPA, EntityHome, and one for
Hibernate, HibernateEntityHome.
The class diagram for EntityHome is shown below:
In the examples that follow, we are focusing on the JPA implementation.
Organization of Code in the Application Framework
As mentioned above, the Home objects are the key. They typically support CRUD operations on the ORM entity
objects. They are also templatized to represent fetching a specific class, including casting the result. In Seam terms,
the DAO is an EJB3 session bean and uses the EntityManager object.
In many small database-driven applications, the CRUD data access logic is the business logic. In large applications,
the benefit of the DAO pattern is that it abstracts out the data access logic from the business logic.
Each of the homes has the following capabilities:








setId() Assign the id. Supplied to the persistence manager to retrieve the instance.
setInstance() Manually establish the instance, bypassing the lookup by id mechanism.
clearInstance() Forcefully clear both the id and the instance.
getInstance() Retrieves the instance managed by this Home object.
isManaged() Reports whether the instance is in a transient or persistent state
persist() Saves the transient instance to the database
update() Synchronizes the persistent instance with the database
remove() Makes the instance transient by removing it from the database
The Home class provides transactional boundaries around the methods on the persistence manager, declared using
Seam’s @Transactional annotation. An excerpt of the persist() method on EntityHome is shown here:
Page 21 of 50
@Transactional
public String persist() {
getEntityManager().persist(getInstance());
getEntityManager().flush();
...
return "persisted";
}
In this method, you can see how the Home is mediating between the entity instance and the persistence manager.
But the Home’s work extends far beyond the boundaries of a transaction. By default, an instance of Home is
scoped to the conversation context, allowing it to maintain the entity instance throughout the use case. When
combined with an extended persistence context, that translates into not having to retrieve the entity instance on each
page transition or having to merge it when changes need to be sent to the database. Instead, the persistence manager
can be responsible for tracking the changes in the entity instance.
Configuring the Seam components to support the Homes
Change the lifecycle to phase-listener to org.jboss.seam.jsf.TransactionalSeamPhaseListener
Se the persistence context to “java:/crudEntityManagerFactory”
In the components.xml file, specify:
<components …>
<core:managed-persistance-context name=”em”
persistence-unit-jndi-name=”java:/crudEntityManagerFactory”/>
</components>
Using the Seam Query Object
The Seam Query object has the same name as its EJB3 counterpart, but has more functionality. It supports paging
of outputs, storage of the current page state (because it is a contextual component), and support for generating the
paging navigator. There is a good example of using the Seam query object for this purpose in Section 10.4 of the
Allen book.
The Seam Query object is a part of the CRUD Application Framework, discussed below. We have pulled the
discussion out to here, because the Seam Query object is usable by itself, and is such a major improvement on the
EJB3 Query object.
The Query component manages contextual queries, which means that the query can change dynamically as its
parameters (which are mapped to context variables) change. Just like the Home component template, there are
implementations of the Query class for both JPA and Hibernate, EntityQuery and HibernateEntityQuery,
respectively.
The methods supported are:
Page 22 of 50
The methods that are supported are:
The way to think about these is as <Next,Prev,Last>FirstResult, because firstResult is what goes into the next fetch
cycle. There is no implementation of <First>FirstResult, because it is always zero.
Displaying Multiple-page Query Results
The Seam Query component has built-in support for paged data tables.
Then, on the JSF page, you use the firstResult HTTP request parameter to control the first record fetched and
displayed.
The Query component provides built-in support for pagination links. That makes it easy to add First/Prev/Next/Last
links to the data result page. Here is an example:
<h1>Search for People</h1>
<h:dataTable value="#{people.resultList}" var="person">
<h:column>
<s:link view="/editPerson.jsp" value="#{person.firstName} #{person.lastName}">
<f:param name="personId" value="#{person.id}"/>
</s:link>
</h:column>
</h:dataTable>
Page 23 of 50
<s:link view="/search.xhtml"
<f:param name="firstResult"
</s:link>
<s:link view="/search.xhtml"
<f:param name="firstResult"
</s:link>
<s:link view="/search.xhtml"
<f:param name="firstResult"
</s:link>
<s:link view="/search.xhtml"
<f:param name="firstResult"
</s:link>
rendered="#{people.previousExists}" value="First Page">
value="0"/>
rendered="#{people.previousExists}" value="Prev Page">
value="#{people.previousFirstResult}"/>
rendered="#{people.nextExists}" value="Next Page">
value="#{people.nextFirstResult}"/>
rendered="#{people.nextExists}" value="Last Page">
value="#{people.lastFirstResult}"/>
Using Seam to Create Clickable Data Tables
At this point, we have covered everything needed to create the typical data management operations of a web
application: listing, displaying, creating, editing, and deleting of data objects. In this case, we are using Seam
facilities that build on the basic JSF datatable, form, and validation facilities.
One of the challenges in JSF datatables is how to link the table to the data model itself. The standard approach is to
use the binding="#{carManager.dataTable}" or similar attribute, where the dataTable field in the manager
object is an instance of HtmlDataTable. There are a number of getters and setters which must be defined for this
purpose.
Seam uses bijection to simplify this greatly.
@Stateless
@Name("portfolioManager")
public class PortfolioManagerAction implements PortfolioManager {
@DataModel
private List<Trade> trades;
@DataModelSelection
private Trade selectedTrade;
@PersistenceContext
private EntityManager em;
..
}
Combined with:
@Factory("trades")
public void find() {
trades = em.createQuery("select p from Trade p").getResultList();
}
The datatable will then refer to #{trades} when getting its content, since this is a globally available and named
object.
The selectedTrade will be updated automatically.
Remember to call find() in the method that starts the display of the portfolio trades.
The @DataModelSelection Seam annotation tells Seam to inject the DataModel List element corresponding to
the clicked link into the item attribute. The @Out Seam annotation transfers the value of this attribute to the item
event context variable, making it available to a JSP page after the action catalog.select method execution.
Page 24 of 50
So when a row of the dataTable is selected, the selected row is injected to the item attribute of the CatalogBean
Stateful bean, and then outjected to the event context variable named item which is used in the Detail.xhtml
page to display the item details.
Seam @DataModel Annotation
In JSF, UIData components, such as <h:dataTable>, are backed by a special collection wrapper called a data
model. A data model is a way for JSF to adapt various types of collections to the UI component model in a consistent
way and to support capturing a row selection made by the user. The collection wrappers extend from the abstract
class javax.faces.DataModel and support the major collection types. Seam builds on this set by adding
support for the Query component from the Seam Application Framework.
The Query component manages the result of a JPQL/HQL query, which Seam retrieves and wraps in a
ListDataModel.. The mapping between the collection types and their wrappers is shown below:
So what do these wrappers have to do with bijection? To properly prepare collection data to be used in a UIData
component, you should wrap it in a JSF data model. Why should you have to deal with this drudgery in your
business logic? This task sounds like something the framework should handle. Seam developers agree.
For this purpose, they created the @DataModel annotation. The @DataModel is used in place of the @Out
annotation for outjecting one of the collection types listed in the table above. Before the value of the @DataModel
property is assigned to the context variable during outjection, it’s first wrapped in the correct JSF DataModel
implementation.
Now, whenever the home page is requested, the findNewGolfers() method prepares the newGolfers context
variable for the view. With the @DataModel annotation, you never have to think about the JSF DataModel
interface; it’s completely transparent. Seam even takes care of reinitializing the context variable whenever a change
is detected in the underlying collection. Your component is free to use properties that are native Java collection
types. Your UI component sees the outjected data as the appropriate DataModel wrapper class. Where this pays
off is in capturing a row selection from the DataModel, again without having to tie your component to the JSF API.
Validating Input Data
If we enhanced the stateful “hello world” to have additional checking on the input fields, such as requiring that a
person have a first name, last name, age between 3 and 100, and an email address that is syntactically valid.
This is located in the example called “integration” – previously we wondered what was being integrated in that
example!
Validation on Entity Beans
You can place @NotNull and @Pattern annotations on the fields in the entity beans. This will cause validation at
runtime, but in particular it will cause validation to be applied to screens for editing such entities.
Page 25 of 50
The validation types that are available include: @Length, @Max, @Min, @NotNull, @Email, @Range, @Size,
@Past, @Future, etc.
It is also possible to specify the validation message in the validation clause. This is a big improvement over JSF,
where you can only specify messages to by class of field.
Here is an example from the trading application:
public class Trade {
… fields …
@Id @GeneratedValue
public long
getId() { return id; }
public void
setId(long id) { this.id = id; }
@Range(min=10, max=20000, message="Number of shares out of range")
public long
getNumberTraded() { return numberTraded; }
public void
setNumberTraded(long nt) { this.numberTraded = nt; }
@Length(min=1, max=5, message="Invalid symbol")
public String getStockSymbol() { return stockSymbol; }
public void
setStockSymbol(String ss) { this.stockSymbol = ss; }
}
Seam validator annotations are the same thing as Hibernate validator annotations.
Triggering the Validation Action
Use the following:
<h:form>
<h:inputText value=”#{person.name}”>
<s:validate/>
</h:inputText>
<h:inputText value=”#{person.age}”>
<s:validate />
</h:inputText>
</h:form>
Or:
<h:form>
<s:validateAll>
<h:inputText value=”#{person.name}” />
<h:inputText value=”#{person.age}” />
</s:validateAll>
</h:form>
Displaying Validation Result Messages
In our earlier JSF applications, we wrote out the label, the input, and the error display HTML for each field
manually. A better approach is to use the Seam s:decorate facility (which is based on Facelets), as shown here:
<s:decorate id="qtyDecorate" template="edit.xhtml">
<ui:define name="label">Quantity:</ui:define>
<h:inputText id="stockSymbol" required="true" value="#{trade.numberTraded}" />
</s:decorate>
Where edit.xhtml is:
Page 26 of 50
<div class="entry">
<s:label styleClass="label #{invalid?'errors':''}">
<ui:insert name="label"/>
<s:span styleClass="required" rendered="#{required}">*</s:span>
</s:label>
<span class="input #{invalid?'errors':''}">
<s:validateAll>
<ui:insert/>
</s:validateAll>
</span>
<s:message styleClass="error errors"/>
</div>
The decorate tag is a kind of macro expander and uses a Facelets facility. It expands out the JSF tags for the label
and the validation facilities.
Workspaces and Concurrent Conversations
Seam can manage several conversations within an HTTP session. This avoids the problem of conflicting posts to
the same session within different windows in the browser, which apparently no other framework property handles.
The example would be making a different trade in each window, and then confirming each one separately. Instead
of the most recently entered trade symbol taking effect, each one is distinct.
In a Seam application, a workspace maps one-to-one with a conversation.
Also, the “Back” button works across conversations/workspaces.
Workspace Switching
You can access the list of current conversations using the symbol #{conversationList}. Often this is used in a table,
to construct a switchable list of conversations, using the following code:
<div class="section">
<h:form>
<a href="home.seam">New workspace</a> |
<a href="home.seam" target="_new">New window</a> |
<h:dataTable value="#{conversationList}" var="entry">
<h:column>
<h:commandLink action="#{entry.select}" value="#{entry.description}"/>
 
<h:outputText value="[current]" rendered="#{entry.current}"/>
</h:column>
<h:column>
<h:outputText value="#{entry.startDatetime}">
<f:convertDateTime type="time" pattern="hh:mm"/>
</h:outputText>
<h:outputText value="#{entry.lastDatetime}">
<f:convertDateTime type="time" pattern="hh:mm"/>
</h:outputText>
</h:column>
</h:dataTable>
</h:form>
</div>
This only works correctly if the conversation and page are given a descriptive label on the pages.xml file. We will
see this file in more detail below, but for now we are using it for page information, and continuing to place the
navigation information using JSF-style facilities in the navigation.xml file. The page descriptive information is
specified as follows:
<pages>
Page 27 of 50
<page view-id="/submitTrade.xhtml">
Entering Trade
</page>
<page view-id="/review.xhtml">
Review Trade for #{trade.stockSymbol}
</page>
</pages>
The workspace listing information appears as follows in the lower part of the screen:
In this example, there were two windows in different tabs (hence in the same session), and one was entering a trade
for CAT and one DOG.
The switcher display code at the bottom was placed into a different .xhtml file and included into each of the primary
screens using the Facelets (ui:include tag).
Carrying a Conversation across Workspaces
As we discussed earlier, Seam creates a new workspace for each HTTP get request. By definition, the new
workspace has its own fresh conversation. So what if we want to do an HTTP get and still preserve the same
conversation context? The solution is to pass in the conversation id, using the “cid” parameter.
A request might look like:
http://localhost:8080/booking/hotel.seam?cid=10&clr=true
“clr” indicates a long-running conversation (i.e., one that is persistent).
If an invalid conversation id given, Seam will display the configured “no-conversation-view-id”, which is specified
in the components.xml file under the core:pages tag.
Managing the Conversation Id
By default, the conversations are numbered sequentially from one.
You can override the numbering by using @Begin(id=“hotel#{hotel.id}”) or a similar approach.
In addition to the conversationId values, Seam allows you to customize the cid and clr HTTP parameters. This is
done as follows:
<components>
<core:manager conversation-timeout-“120000”
concurrent-request-timout=“500”
Page 28 of 50
conversation-id-parameter=”cid”
conversation-is-long-running-parameter=”clr” />
</components>
Bookmarkable Pages
One of the loudest criticisms of JSF (and other component-based web frameworks) is its reliance on HTTP Post
requests. JSF uses HTTP Post to match user actions (i.e., button clicks), with UI event handler methods on the
server side (i.e., in Seam stateful session beans). It also uses hidden fields in the HTTP Post request to keep track of
the user’s conversational state.
The problem is that the URL of a post doesn’t contain enough information to be complete. Hence you can’t book
mark such a page. This would be highly desirable on many e-commerce sites. This is also important for pages and
web applications set up to use REST, which based on Representational State Transfer.
There are two approaches to doing this better: page parameters, and Java-centric approach based on annotations.
In page parameters, you page a page id on each page description in the pages.xml file.
In the Java-centric approach (the term appears to be derived from the idea that this is similar to standard Java action
classes such as in Struts), you use a Seam annotation that will inject parameters of the HTTP request, such as the
record id, and from that you can fetch the appropriate information.
Getting the request query parameter is only the first step. When the page is loaded, it also has to trigger Seam to
actually fetch the correct information. This is done with a Factory method.
Finally, you can use a hidden field to hold an Id, as is often done in Struts. However, the Seam book points out that
this is really a hack.
In conclusion, Seam provides REST support for JSF application. This is one of the most compelling reasons to use
Seam with JSF.
Securing Seam Applications
Seam has a security facility that is distinct from, or a level above, EJB security.
This uses the built-in global object called “Identity”. The identity object is one which supports login and logout
methods. There is a simple default such object, but you will typically extend and override it.
Authentication
You write an authentication method, and register it with the Identity facility using a component.xml file element.
This will be called when the application performs Identity.login().
Next, you can have a set of roles associated with the user.
Authorization
You can secure pages by using notations on the components for the pages. This can be specified in the page actions.
A more advanced security system uses rule-based authorization based on the Drools engine. This could break out
into a developer topic of its own. It isn’t covered until the back of the Allen book, and is not in much detail.
Captcha
There is a Captcha facility available, just as we built in one of the Wicket examples back in December 2008.
Page 29 of 50
Other Topics
Display JSF Messages
Besides supporting correct ORM lazy loading, the default Seam conversation scope helps improve JSF by
expanding the JSF support for error messages.
In typical JSF, when an operation fails, the backing bean could add a message to the JSF context and return null.
The JSF runtime can then redisplay the current page with error messages added. In Seam, this is easier, because you
can directly inject a FacesMessages object into the Seam component. The following is an example:
@Stateful
@Name(“manager”)
@Scope(SESSION)
public class ManagerAction implements Manager {
@In @Out
private Person person;
@In
FacesMessages facesMessages;
public String sayHello() {
try {
..
}
catch (Exception e) {
facesMessages.add(“Problem saving #{person.name}”);
return null;
}
return “fans”;
}
}
Debug Management and Facilities
First it is important to understand the error management tools provided in JSF. This includes the error-page
declaration in web.xml, which allows you to declare what page is shown for what HTTP error, such as 404, or by
class of exception thrown.
However, a problem with this approach is that the JSF servlet wraps around the exception from the business layer
and throws a generic ServletException instead, before the server captures the exceptions and redirects to the error
page. So you cannot accurately specify the actual exception from the business layer.
In the JSP world, a workaround exists, which is to redirect to a JSF error page and use the global variable
“exception”. Then you can drill down to the root cause of the exception and display the appropriate message.
Unfortunately this does not work correctly JSF-rendered JSP page or in Facelets pages.
The first level of the Seam approach is to use the Seam filter to resolve exceptions. Make sure that your web.xml
file specifies the Seam filter, as documented above. With this filter set up, you can now specify custom error pages
for exceptions via one of the following two ways: for application–defined exceptions, you can use annotations and
for system or framework exceptions, you can use the pages.xml file.
Annotating Exceptions
In Seam, you can annotate the specialized subclasses of Exception to trigger page-level behavior when they happen.
This is something that we had to put into the mainController class in the older Incra framework code. For instance,
you could define InventoryException as:
Page 30 of 50
@ApplicationException(rollback=true)
@Redirect(viewed=”/inventoryError.xhtml”)
public class InventoryException extends Exception {
public InventoryException() {}
}
This will cause your application to jump to inventoryError.xhtml when an error occurs. A typical layout of an error
page would be:
<ui:composition template=”template.xhtml”>
<ui:define name=”content”>
<h1>Insufficient Inventory</h1>
Try a different hotel
</ui:define>
</ui:composition>
Notice that we do not display the exception state even though it is available.
The @HttpError produces a different kind of exception, which creates an Http Error code to the browser, such as
404.
Using pages.xml for System Exceptions
In a Seam application, you can configure how to deal with system or framework exceptions via the pages.xml file.
In an approach that is similar to the global error handlers of Struts configuration files, you define <exception> tags
that indicate the class of exception, and what to do, such as ending a conversation, redirecting to a particular view,
etc.
The Debug Information Page
To enable the Facelets debug page, you need to set the Facelets in development mode, as follows:
<web-app>
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
</web-app>
If an error occurs, the resulting page provides good line information about the point of the error.
To enable the Seam debug page, you must make the following indications in the components.xml file:
<components>
<core.init jndi-pattern=”booking/#{ejbName}/local”
debug=“true” />
</components>
Now any uncaught error will be directed to the debug.seam page, which shows the session context, the application
context, and the exception stack.
Again, the debug.seam page works even if there is no error. You can load that page at any time to look at the
current Seam runtime context information.
Seam Testing
Now that we have discussed the structure of the generated Seam application, we can discuss the testing facilities
within Seam. These are discussed at this point because they are provided within the Seam Gen produced code, and
make use of a subset of the Seam CRUD app framework.
Page 31 of 50
Most Seam applications will need at least two kinds of automated tests: unit tests, which test a particular Seam
component in isolation, and scripted integration tests which exercise all Java layers of the application (that is,
everything except the view pages).
Both kinds of tests are very easy to write.
Unit Tests
All Seam components are POJOs. This is a great place to start if you want easy unit testing. And since Seam
emphasizes the use of bijection for inter-component interactions and access to contextual objects, it's very easy to
test a Seam component outside of its normal runtime environment.
Consider the following Seam component:
@Stateless
@Scope(EVENT)
@Name("register")
public class RegisterAction implements Register {
private User user;
private EntityManager em;
@In
public void setUser(User user) {
this.user = user;
}
@PersistenceContext
public void setBookingDatabase(EntityManager em) {
this.em = em;
}
public String register() {
List existing = em.createQuery("select username from User where
username=:username")
.setParameter("username", user.getUsername())
.getResultList();
if (existing.size()==0) {
em.persist(user);
return "success";
}
else {
return null;
}
}
}
We could write a TestNG test for this component as follows:
public class RegisterActionTest {
@Test
public testRegisterAction() {
EntityManager em = getEntityManagerFactory().createEntityManager();
em.getTransaction().begin();
User gavin = new User();
gavin.setName("Jeff Risberg");
gavin.setUserName("jrisberg");
gavin.setPassword("secret");
Page 32 of 50
RegisterAction action = new RegisterAction();
action.setUser(gavin);
action.setBookingDatabase(em);
assert "success".equals( action.register() );
em.getTransaction().commit();
em.close();
}
private EntityManagerFactory emf;
public EntityManagerFactory getEntityManagerFactory()
{
return emf;
}
@Configuration(beforeTestClass=true)
public void init()
{
emf = Persistence.createEntityManagerFactory("myResourceLocalEntityManager");
}
@Configuration(afterTestClass=true)
public void destroy()
{
emf.close();
}
}
Seam components don't usually depend directly upon container infrastructure, so most unit testing is as easy as that!
Integration Tests
Integration tests are those which do depend upon the container infrastructure, such as having components and
context, persistence and transactions, etc. Seam uses two technologies in combination:


The Embedded JBoss container – this is run-time subset of JBoss itself, which can run at the command line
TestNG – this is a test framework that is considered to be a successor to JUnit. It has a number of
advantages including being driven by a configuration file, and allowing for groups of tests, dependencies
between tests, and even parallel testing. See also our document “Notes on Java Unit Testing”.
You create a subclass of SeamTest. For instance, here is an example:
package com.incra.alpha.test;
import org.testng.annotations.Test;
import org.jboss.seam.mock.SeamTest;
public class RegisterActionTest extends SeamTest {
@Test
public void test_register() throws Exception {
new FacesRequest() {
@Override
protected void invokeApplication() {
//call action methods here
invokeMethod("#{registerAction.register}");
}
Page 33 of 50
}.run();
}
}
This approach runs the embedded JBoss container, rather than starting up the whole JBoss server.
One gotcha is that the Embedded JBoss container only runs with Java 1.5, according to the release notes. However,
there is a note on the web about using Java 1.6, and making a simple change to support it. See
http://seamframework.org/Community/SeamTestWithJava16InJBoss423
If you want to run tests using the Eclipse TestNG plugin, you'll need to add these jars to the top of your TestNG
classpath. Using the Run Dialog, select xml suite to run, and add /lib/test/jboss-embedded-all.jar, /lib/test/hibernateall.jar, /lib/test/thirdparty-all.jar, /lib/jboss-embedded-api.jar, /lib/jboss-deployers-client-spi.jar, /lib/jbossdeployers-core-spi.jar, and /bootstrap as the first entries in the User classpath. To add tests to your project create a
TestNG xml descriptor called *Test.xml e.g. FooTest.xml next to your test classes and run ant test.
This suggests adding the following to the invocation of TestNG as a target in your build.xml script:
<testng outputdir="${basedir}/test-report">
<classpath refid="test.path"/>
<!--<jvmarg value="-Demma.coverage.out.file=${coverage.ec}" />-->
<jvmarg line="-Djava.awt.headless=true"/>
<!--added for JDK6 compatibility with JBoss embedded-->
<jvmarg line="-Dsun.lang.ClassLoader.allowArraySyntax=true"/>
<xmlfileset dir="${test.dir}" includes="*Test.xml"/>
</testng>
This in turn requires that you add the <taskdef resource="testngtasks" classpath="${testng.jar}"
/> to the build.xml file.
Finally, you will add a test specification file (this is something specific to TestNG, and different from JUnit), which
defines the test to run. This is typically something like:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Suite1" verbose="1" >
<test name="Nopackage" >
<classes>
<class name="NoPackageTest" />
</classes>
</test>
<test name="Regression1" >
<classes>
<class name="test.sample.ParameterSample" />
<class name="test.sample.ParameterTest" />
</classes>
</test>
</suite>
One complication that we found is that by default, SeamTests use the HSQL database (an in-memory store), but it
can be adapted to use MySQL. This requires adding a MySQL driver to the libraries placed into the bootstrap, and a
*-ds.xml file to define the parameters. There is documentation on this at
http://seamframework.org/Documentation/HowDoIUseADifferentDatabaseWithEmbeddedJBoss.
However, one final issue is that for some reason, the Embedded JBoss container doesn’t support the “metadata”
service in a data source. Hence, you will need to remove the “metadata” tag from the *-ds.xml file, leaving
something like this:
<!DOCTYPE datasources PUBLIC "-//JBoss//DTD JBOSS JCA Config 1.5//EN"
Page 34 of 50
"http://www.jboss.org/j2ee/dtd/jboss-ds_1_5.dtd">
<datasources>
<local-tx-datasource>
<jndi-name>SE02Datasource</jndi-name>
<connection-url>jdbc:mysql://localhost:3306/se02</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>developer</user-name>
<password>123456</password>
<!-- metadata service is not available in the Embedded JBoss, so don't put it in here -->
</local-tx-datasource>
</datasources>
There is currently no TestNG test runner for use in Eclipse, so it is preferable to run TestNG as an ANT script target.
The Seam-Gen produced build.xml file has exactly this level of support.
Seam Page Flow System
In JSF we used the navigation rules of the navigation.xml or faces-config.xml file to define all of the page
flow rules, such as “from view A go to view B”. An example was:
<navigation-rule>
<from-view-id>/greeting.jsp</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/response.jsp</to-view-id>
</navigation-case>
</navigation-rule>
You can reference those rules from links/buttons on web pages to specify which page to display when the
link/button is clicked. When an event-handler method is invoked from a link/button, the method returns a literal
string value that matches one of the navigation rules to determine which page to display next. That works well in
simple applications. However, as web applications grow more complex, many potential outcomes could result from
an event-handler method, and multiple navigation rules might point to the same target page. The navigation.xml
or faces-config.xml files could quickly become bloated and hard to debug.
This approach is termed the “stateless model”, as it defines a mapping from a set of named, logical outcomes of an
event directly to the resulting page of the view. The navigation rules are entirely oblivious to any state held by the
application other than what page was the source of the event. This means that your action listener methods must
sometimes make decisions about the page flow, since only they have access to the current state of the application
Stateful Navigation Rule in pages.xml
While this can still be used in Seam, there is an alternate way to manage the navigation rules. Instead of relying on
the event-handler methods to return the exact literal strings, a Seam application can automatically determine the next
page to display based on the actual state of the application. We have mentioned the pages.xml file briefly earlier as
as way of configuring page-level information, but to understand how the navigation works, let's look at an example.
<page view-id="/register.xhtml">
<action if="#{validation.failed}" execute="#{register.invalid}"/>
<navigation>
<rule if="#{register.registered}">
<redirect view-id="/home.xhtml"/>
</rule>
</navigation>
</page>
First of all, these definitions are page-centric, which means that you could divide the file or files up into different
sections for the different groups of pages assigned to developers. Also, each page can have a set of actions and rules
Page 35 of 50
which in turn can access information in the Session and Entity beans of the application. In the above example, we
are going to the home page if we completed registration, but there are also error handling pages.
Here is another example:
<navigation from-action="#(orderHandler.submit}">
<redirect view-id="/review.xhtml"/>
</navigation>
This looks like a hybrid of the JSF and Seam approaches.
Also, a page can indicate that it is only available when the user is logged in. This is done through the “loginrequired” attribute on the page.
The structure of the pages.xml file also includes two global specifications:
 The no-conversation-view-id – defined below
 The login-view-id – this is the view that is jumped to when the user tried to access a login-required page
and he is not logged in.
A combined file, therefore, is as shown below:
<pages xmlns="http://jboss.com/products/seam/pages"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.com/products/seam/pages
http://jboss.com/products/seam/pages-2.0.xsd"
no-conversation-view-id="/main.xhtml"
login-view-id="/home.xhtml">
<page view-id="/register.xhtml">
<action if="#{validation.failed}" execute="#{register.invalid}"/>
<navigation>
<rule if="#{register.registered}">
<redirect view-id="/home.xhtml"/>
</rule>
</navigation>
</page>
…
</pages>
A typical rule is from a given view-id, such as /register.xhtml”, and it has a triggercondition which is if the user
registered, then go to the home.xhmtl screen.
When JSF navigation rules are used, Seam lets the user freely navigate via the back, forward and refresh buttons. It
is the responsibility of the application to ensure that conversational state remains internally consistent when this
occurs. Experience with the combination of web application frameworks like Struts or WebWork - that do not
support a conversational model - and stateless component models like EJB stateless session beans or the Spring
framework has taught many developers that this is close to impossible to do! However, our experience is that in the
context of Seam, where there is a well-defined conversational model, backed by stateful session beans, it is actually
quite straightforward. Usually it is as simple as combining the use of no-conversation-view-id with null
checks at the beginning of action listener methods. We consider support for freeform navigation to be almost
always desirable.
In this case, the no-conversation-view-id declaration goes in pages.xml. It tells Seam to redirect to a
different page if a request originates from a page rendered during a conversation, and that conversation no longer
exists:
Page 36 of 50
<page view-id="/checkout.xhtml"
no-conversation-view-id="/main.xhtml"/>
On the other hand, in the stateful model, backbuttoning is interpreted as an undefined transition back to a previous
state. Since the stateful model enforces a defined set of transitions from the current state, back buttoning is by
default disallowed in the stateful model! Seam transparently detects the use of the back button, and blocks any
attempt to perform an action from a previous, "stale" page, and simply redirects the user to the "current" page (and
displays a Faces message).
Seam Logging
Who is not totally fed up with seeing noisy code like this?
private static final Log log = LogFactory.getLog(CreateOrderAction.class);
public Order createOrder(User user, Product product, int quantity) {
if ( log.isDebugEnabled() ) {
log.debug("Creating new order for user: " + user.username() +
" product: " + product.name()
+ " quantity: " + quantity);
}
return new Order(user, product, quantity);
}
It is difficult to imagine how the code for a simple log message could possibly be more verbose. There is more lines
of code tied up in logging than in the actual business logic! I remain totally astonished that the Java community has
not come up with anything better in 10 years.
Seam provides a logging API built on top of Apache commons-logging that simplifies this code significantly:
@Logger private Log log;
public Order createOrder(User user, Product product, int quantity) {
log.debug("Creating new order for user: #0 product: #1 quantity: #2",
user.username(), product.name(), quantity);
return new Order(user, product, quantity);
}
It doesn't matter if you declare the log variable static or not—it will work either way.
Note that we don't need the noisy if ( log.isDebugEnabled() ) guard, since string concatenation
happens inside the debug() method. Note also that we don't usually need to specify the log category explicitly,
since Seam knows what component it is injecting the Log into.
If User and Product are Seam components available in the current contexts, it gets even better:
@Logger private Log log;
public Order createOrder(User user, Product product, int quantity) {
log.debug("Creating new order for user: #{user.username} product: #{product.name}
quantity: #0", quantity);
return new Order(user, product, quantity);
}
Page 37 of 50
Ajax and JavaScript Remoting
Using Ajax with JSF
JSF beat Ajax mania to the scene by nearly a year. The order of events was unfortunate because Ajax would have fit
perfectly with the design of JSF as an event-driven framework backed by a server-centric model.
Although Ajax wasn’t included in the JSF specification (and still isn’t as of JSF 1.2), innovators recognized the
potential of Ajax to close the gap in the JSF vision and adapted it to JSF in an intelligent and efficient manner. This
section talks about the right and wrong ways of using Ajax with JSF, the two main component libraries that brought
Ajax to JSF, and Seam’s role in Ajax-based JSF requests.
The challenge of introducing Ajax into JSF is that the standard UI components, and plenty of third-party UI
components, have no awareness of Ajax. Rather than mandating that you switch to an Ajax-based UI component
set, RichFaces developer Alexander Smirnov developed a way to weave Ajax into JSF transparently, a solution now
known as Ajax4jsf. The mechanism he invented is so transparent, in fact, that it can be used to “Ajax-enable” any
JSF page without the UI components having any awareness they’re participating in an Ajax request. This one library
took JSF from being Ajax-inept to being one of the most compelling approaches to Ajax.
While the Ajax4jsf component library contains a broad set of UI component tags, the tag that gets the heaviest use,
almost disproportionately so, is <a:support> (often written as <a4j:support>). It’s used to bind a userinitiated JavaScript event to a serverside action invoked via Ajax and to designate regions of the page that get
rerendered from the Ajax response, encompassing the essence of Ajax4jsf.
While the Ajax requests allow the page to continuously interact with Seam, there’s nothing that Seam has to do
differently. The JSF life cycle is still invoked and therefore Seam treats each request just as it would any other
postback. That doesn’t mean Seam has nothing to add, though. On the contrary, you find that Seam’s stateful design
lends itself perfectly to the Ajax-enabled JSF environment. Here are a few ways Seam adds value:




Maintain server-side state —Seam can connect the state from one Ajax request to the next, avoiding the
negative impact of pounding the server’s resources. Both the page scope and a long-running conversation
work well here. Seam can even facilitate an application transaction performed entirely over Ajax.
Contribute outjected context variables —Any action invoked during an Ajax request can trigger bijection.
The outjected context variables are available to the regions of the view being rerendered.s
Dry-run the JSF life cycle —Ajax4jsf can ask JSF to run through the life cycle without performing actions
or navigations to verify that form data is acceptable. Seam’s integration with Hibernate Validator is of most
interest here.
Notify changes in application state —Seam’s event/observer model, its asynchronous dispatcher, and its
integration with JMS offer ways to notify components of a change in the application’s state. When
combined with ICEfaces’ Ajax Push, presentation changes can be sent to browsers with having to wait for
interaction from the user.
Aside from the last point, the items in this list remain consistent with points made throughout the book. The only
difference now is that everything is happening in closer to real time and the browser isn’t spinning its wheels
reloading the page. You do need to be aware that Ajax requests occur more frequently, so there’s a greater chance
that multiple requests in the same conversation will arrive at the server simultaneously.
Partial Form Submits
One of the most frequently requested features in JSF is client-side form validation. Although there are certainly
benefits to the performance and near real-time execution of client-side validation, there are equal benefits to having
these validations performed on the server instead. Even if the validation passes in the UI, it’s still necessary to
validate on the server since JavaScript validation can’t be trusted (execution of JavaScript is voluntary). In addition,
validations often need access to server-side resources to arrive at a decision. Thus, client-side validation doesn’t
provide that much value. What developers are really asking for is instant, or “live,” validation. That doesn’t mean it
has to happen strictly on the client.
Page 38 of 50
JavaScript remoting to Seam
JavaScript remoting is an alternative to Ajax-based JSF requests for establishing a channel of communication
between the browser and the server. It supports using JavaScript to invoke a method on a server-side object as if it
were local to the browser.
Seam’s JavaScript remoting library is inspired by the Direct Web Remoting ( DWR) project,4 but designed
specifically for accessing Seam components. The interaction with the server-side object is performed using Ajax
requests, but the requests are encapsulated within dynamically generated JavaScript proxy objects, so you never
have to interface with the XMLHttpRequest object directly.
In JavaScript remoting, the client (browser) and the server (Seam container) are fused together as one, establishing a
continuity between local and remote operations. The interchange between the client and server during a remoting
request resembles a conventional remote procedure call (RPC) over Java RMI or SOAP, except that JavaScript
remoting is far more lightweight and mostly transparent to the developer.
Here’s a sampling of tasks that are well suited as JavaScript remoting tasks:
 Facilitating a user interaction that’s tangential to the rendered page
 Persisting entities that don’t have a visual representation
 Starting and completing tasks in a business process
 Sending an email in response to a user-triggered event
 Transmitting a user interface error or statistic to the server to be logged
 Monitoring or polling for a value maintained on the server
Conversational Remoting calls
There are two ways for JavaScript remoting requests to partake in conversations. They can join the conversation
associated with the current page, or they can go off and establish their own conversation, isolated from and
transparent to the rendered page.
There are two scenarios for using conversations with JavaScript remoting.


Conversation management
Storing up requests for a shipment
Responding to GWT Remoting calls
As you lean more toward the single-page application, you may reach a point where JSF just doesn’t fit any longer. If
that’s the case, you are probably better off moving to a UI framework that’s designed around the use of remoting
calls. One such library is the Google Web Toolkit (GWT). A move from JSF to GWT doesn’t mean that you have to
leave Seam behind. GWT is intended for creating the user interface, which means it must delegate work to
transactional components on the back end. Seam remoting can establish that bridge.
Seam Web Services
Seam web services use a custom web request handler class that saves and stores conversational state. This is
described in the reference manual.
PDF Generation
Since PDF generation is important for the production of invoices and workorders, we call it out here.
This facility is provided by the seam-pdf.jar lbrary, which uses the iText library. While iText provides a set of
classes and methods that can be used to describe and render a PDF page or file, it is intended for a Java programmer
to call, and hence requires compilation if there are changes.
Page 39 of 50
Seam-pdf takes the approach of moving page layout into the .xhtml file, with a set of tags that define components
just as JSF uses tags to define components. Here is an example:
<p:document xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://jboss.com/products/seam/pdf"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:s="http://jboss.com/products/seam/taglib"
title="Example PDF Document" creator="SE02" pageSize="LETTER"
type="#{not empty param.type ? param.type : 'pdf'}" >
<p:font size="18">
<p:paragraph>Electronic Supply Chain Association</p:paragraph>
</p:font>
<p:font size="12" color="darkgray">
<p:paragraph>Member Roster</p:paragraph>
</p:font>
<p:list listSymbol="-">
<ui:repeat value="#{organizationList.resultList}" var="org" >
<p:listItem>#{org.name}</p:listItem>
</ui:repeat>
</p:list>
</p:document>
The primary tags in the seam-pdf library are:
 p:document
 p:paragraph
 p:text
 p:font
 p:image
 p:newPage
 p:list
 p:listItem
Basic Tags
Tags such as p:document allow you to define the page size and settings. Tags such as p:paragraph are the mostly
commonly used, as these generate the visible text, and there are no tags for generating graphics or very complex
page appearance. In fact, this wrapper over iText is nowhere near as comprehensive as iText itself. The color
management facilities are limited (in Seam 2.0.x, you can only use the 12 basic named colors (such as red, green,
cyan, white, black, etc., but this was expanded to an RGB-based color system in release 2.1.x).
You can specify the font to be used for the text.
You can build a list, but you can’t change the background color of the list items. Actually you can’t change the
background color of any basic element.
There is a tag that will generate PDF for HTML text, but it supports mostly the simple text information, and appears
to ignore content that cannot be converted to the capabilities of the p: tags. Hence this was not as useful as we were
hoping.
The best way to get interesting visual appearance is to add images. These can be gif or jpg images loaded from the
disk, or generated images.
Tables
There is an entire facility for creating tables. This uses the tags such as p:table, and p:cell, and each cell can have
formatting information such as background color, border color, etc. If you want to produce any complex layout or
Page 40 of 50
formatting, this is the way to do. The table cells can include p:paragraph tags and p:image tags. See the reference
manual for more details on these tags.
Chapters and Sections
There is a facility for organizing the document into chapters and sections. This aids in creating the table of contents
of a PDF.
Headers and Footers
The p:header and p:footer components provide the ability to place header and footer text on each page of a
generated document, with the exception of the first page. Header and footer declarations should appear near the top
of a document. In Seam 2.0.x (at least), this model is limited: you can’t produce images in the header or footer,
only text.
The current page number can be placed inside of a header or footer using the p:pageNumber tag. The page
number tag can only be used in the context of a header or footer and can only be used once. The documentation
says that headers and footers only appear on the non-first page. This begs the question as to how to produce a footer
for the first page, and in fact, we couldn’t get the headers or footers to work as expected in general, when running
Seam 2.0.x.
Using iText Directly
A user could skip the seam tags and just call iText to generate a page programmatically. This is described in our
document “Notes on iText”, and in the link http://threebit.net/mail-archive/itext-questions/msg04296.html.
Charting
Just as Seam provides tags that create the PDF elements, it also contains tags that define charting elements, using the
JFreeChart library.
There are three such tags:
 p:barchart
 p:linechart
 p:piechart
Along with the p:series and p:data tags, these define the information for a chart. Here is an example:
<p:barchart title="Bar Chart" legend="true"
width="500" height="500">
<p:series key="Last Year">
<p:data columnKey="Joe" value="100"
<p:data columnKey="Bob" value="120"
</p:series>
<p:series key="This Year">
<p:data columnKey="Joe" value="125"
<p:data columnKey="Bob" value="115"
</p:series>
</p:barchart>
/>
/>
/>
/>
In an application, this is often coded as a loop over the series tag (wrapping a ui:repeat around them), where each
series tag has a p:data tag that fetches a value from the backing bean. You can also write a loop around the series
tags and a loop for the p:data tags, or even have the data tags located in different copies of the series tags. In all
usage, each p:data tag defines one data value (there is no data tag that fetches a list from the backing bean).
A number of parameters of the chart can be changed through attributes on these tags, such as the background color
(use “borderBackgroundPaint”), and whether or not the chart should be made by calling createXChart3D (use
Page 41 of 50
“is3D”). What you can’t change is the behavior of the rendering, as you cannot specify the class names of the
rendering objects. Hence, no custom renderers can be used.
Seam Business Process Management
Probably the most advanced facility within Seam is the integration of jBPM and Drools. Of these, jBPM is the more
fundamental, as the idea of a long-running conversation is matched to the idea of a business process. There is a 46page bonus chapter on jBPM in Seam as part of the Allen “Seam in Action” book.
Seam makes it easy to attach jBPM processes to Seam stateful components, because of Seam’s declarative approach
to BPM.
BPM integration is what makes Seam stand out from just about all of the other web-oriented frameworks available
today. The Seam development team recognized that single-user interactions only account for a portion of the use
cases in enterprise applications. Multiuser processes are just as relevant and have a much greater impact on the
application’s effectiveness. That’s why Seam does far more than just provide a jBPM module to nudge along the
tasks in a business process. Seam folds business processes into the Seam container by relying on these key
coordinators:




The business process context—Seam assimilates the stateful context bound to the process instance as one of
its own. Business process–scoped context variables are exchanged with the jBPM process context
transparently, but are otherwise treated just like any other context variable. They can participate in
bijection and can be resolved using EL notation. Value expressions can also be used in the process
definition descriptor to resolve context variables from the Seam container.
Declarative business process controls—A set of annotations and page descriptor tags are included that can
initiate or resume a process instance, start and end tasks, and bring variables from an active process into
scope, all without having to interact directly with jBPM. Seam also includes a set of UI controls for
selecting the process or task instance on which to operate.
Identity management—Similar to the identity component, Seam provides a basic component named
actor for registering the actor id and group ids that will be passed on to the process instance to record the
current participant. The actor component is typically populated during the authentication routine.
User code interceptor—Seam traps executions within a business process instance and sets up the Seam
contexts so that the executions have access to the Seam container.
The main reason business processes are so attainable in Seam is because you can use them without ever having to
make your code interface with jBPM directly. You don’t have to worry about how definitions are loaded, how
processes are kicked off, or how signals are sent to the process instance to advance tasks. Seam handles all of those
low-level details. Your application uses metadata to declare where, and under what conditions, you want these
operations to occur.
The sample application for this use of Seam is the “ticketing” application.
See also our related document “Notes on jBPM”.
jBPM Basics and Vocabulary
Processes are in a process-definition.xml file. A process is made up of nodes, tasks, and a start/end pair. There are
also joins and forks.
The JBoss Eclipse IDE generates XML files for the process definitions. These have tags such as “start-state”, “endstate”, “task-node”, and “decision”. Nodes can have transitions which can have actions.
With Seam, you bind Seam components directly to the jBPM process definition documents using the #{} notation.
Page 42 of 50
Application Users and jBPM Actors
A process typically involves multiple people. For instance, the answer task should be visible to only the admin
Actor. This is configured as:
<task-node name=”process”>
…
<task name=“answer”
description=“#{ticket.title}” >
<assignment pooled-actors=”Admin” />
</task>
…
</taskNode>
Creating a Business Process
@Stateless
@Name(“ticketSystem”)
public class TicketSystemAction implements TicketSystem {
@CreateProcess(definition=”ticketProcess”)
public String newTicket() {
return “home”;
}
…
}
Now whenever the user invokes the newTicket() method, a process instance based on the TicketProcess process
definition is created.
Note that in this case the creator is stateless, while the state is maintained in the process instance.
To bind data objects to the process scope, use @Out(scope=BUSINESS_PROCESS). These objects must be
serializable.
Managing Tasks
Use the @BeginTask and @EndTask annotations to mark the business logic for a task.
When the task is completed, the process moves to the next task.
Display a list of tasks in the UI using the #{poolTaskInstanceList} variable.
Here is an example that displays assigned tasks:
<h:dataTable value="#{taskInstanceList}" var="task">
<h:column>
#{task.description}
</h:column>
<h:column>
<div>
Title: #{ticket.title}
</div>
<h:commandLink action="#{ticketSystem.reply}">
<h:commandButton value="Reply"/>
<f:param name="taskId" value="#{task.id}"/>
</h:commandLink>
</h:column>
</h:dataTable>
There are several filtered versions of this also available.
Page 43 of 50
jBPM Libraries and Configuration
Bundle the jbpm-x-y-z.jar file, which must be version 3.1.2 or later. Seam appears to include the 3.2.2 version
(from about 2007).
Associating a Business Process with a Web Page
Use the following:
<pages>
<page view-id=”/numberGuess.xhtml”>
<begin-conversation join=”true”
pageflow=”numberGuess” />
</page>
<page view-id=”/confirm.xhtml”>
<begin-conversation nested=”true”
pageflow=”cheat” />
</page>
</pages>
Page Flow and Stateful Conversations
<pageflow-definition name=”numberGuess”
<page name=”win” view-id=”/win.xhtml”>
<redirect/>
<end-conversation>
</page>
<page name=”lose” view-id=”/lose.xhtml”>
<redirect/>
<end-conversation>
</page>
</pageflow-definition>
Configuration
To use the jBPM-base pageflows, you must bundle the jBPM library (3.1.2 or later) and the process-definition files
(i.e., the *.jpdl.xml files) in your application.
You need to declare the pageflow definition files to Seam via the core.Jbpm component the components.xml file.
Seam Drools Integration
Seam includes Drools for use in writing authorization manager expressions.
See our document “Notes on Drools” for more details.
File, Rich Rendering, and Email Support
Uploading files and rendering dynamic images – Seam provides components for support of uploads and a wrapper
around the JSF graphic image tag that provides for resizing and generation and images.
Seam is well-matched to using Rich Faces, in fact many Seam applications use Rich Faces. This provides a new set
of GUI components, including tab bars, panels, trees, menus, and scroll bars. See our document “Notes on Rich
Faces”.
Composing email the Seam way – Seam provides a number of email generation components. See the reference
manual for details.
Page 44 of 50
Customizing the UI with resource bundles – Seam provides the SeamBundle component.
Analysis of the Booking Example Application
This is provided in the Seam 2.0.2 distribution, and ran without problems. The entity beans are:
 Hotel is an entity bean that represents a hotel
 Booking is an entity bean that represents an existing booking
 User is an entity bean to represents a user who can make hotel bookings
The remote interfaces of the session beans are
 BookingListAction retrieves existing bookings for the currently logged in user.
 ChangePasswordAction updates the password of the currently logged in user.
 HotelBookingAction implements the core functionality of the application: hotel room searching,
selection, booking and booking confirmation. This functionality is implemented as a conversation, so this is
the most interesting class in the application.
 RegisterAction registers a new system user
Each of these has a corresponding implementation object.
The pages are:
 book.xhtml – enters a booking
 confirm.xhtml – not sure
 display.xhtml – displays a booking
 edit.xhtml – edits a booking?
 home.xhtml – shows an introduction screen
 hotelview.xhtml – views information about one hotel
 index.html – this forwards to main.seam.
 main.xhtml – offers a search of hotels, home offers a title header, and a chance to log in
 password.xhtml – asks for your password
 register.xhtml – creates a new user account
 template.xhtml – this is the common template for all Facelets pages
There are the following conversations:
booking
There are two cascading style sheets:
screen.css (used on the operational screens) and trailblazer.css (used on the explanation screens)
The page flows are:
<pages no-conversation-view-id="/main.xhtml" login-view-id="/home.xhtml">
<page view-id="/main.xhtml" login-required="true">
<navigation from-action="#{hotelBooking.selectHotel(hot)}">
<redirect view-id="/hotel.xhtml"/>
</navigation>
<navigation from-action="#{bookingList.cancel}">
<redirect/>
</navigation>
</page>
<page view-id="/home.xhtml">
<navigation>
<rule if="#{identity.loggedIn}"> <!--this is where you log in -->
<redirect view-id="/main.xhtml"/>
</rule>
</navigation>
</page>
Page 45 of 50
<page view-id="/password.xhtml" login-required="true">
<navigation>
<rule if="#{changePassword.changed}">
<redirect view-id="/main.xhtml"/>
</rule>
</navigation>
</page>
<page view-id="/hotel.xhtml" conversation-required="true" login-required="true">
<description>View hotel: #{hotel.name}</description>
<navigation from-action="#{hotelBooking.bookHotel}"> <-- given hotel, make a booking -->
<redirect view-id="/book.xhtml"/>
</navigation>
</page>
<page view-id="/book.xhtml" conversation-required="true" login-required="true">
<description>Book hotel: #{hotel.name}</description>
<navigation from-action="#{hotelBooking.setBookingDetails}">
<rule if="#{hotelBooking.bookingValid}"> <!-- enters the booking, asks to confirm -->
<redirect view-id="/confirm.xhtml"/>
</rule>
</navigation>
</page>
<page view-id="/confirm.xhtml" conversation-required="true" login-required="true">
<description>Confirm booking: #{booking.description}</description>
<navigation from-action="#{hotelBooking.confirm}">
<redirect view-id="/main.xhtml"/>
</navigation>
</page>
<page view-id="/register.xhtml">
<action if="#{validation.failed}" execute="#{register.invalid}"/>
<navigation>
<rule if="#{register.registered}">
<redirect view-id="/home.xhtml"/>
</rule>
</navigation>
</page>
<page view-id="*">
<!-- from anywhere, are these on some sort of sidenav? -->
<navigation from-action="#{identity.logout}">
<redirect view-id="/home.xhtml"/>
</navigation>
<navigation from-action="#{hotelBooking.cancel}">
<redirect view-id="/main.xhtml"/>
</navigation>
</page>
<exception class="org.jboss.seam.security.NotLoggedInException">
<redirect view-id="/home.xhtml">
<message severity="warn">You must be logged in to use this feature</message>
</redirect>
</exception>
</pages>
It is not clear to us why, if the goal is to avoid XML configuration files, we can’t put this information into the
classes themselves.
Appendix A: Seam Libraries and Services
Minimal Requirements
Assuming that you have JBoss 4.2.3, the extra libraries required for Seam are only jboss-seam.jar.
If you are using Facelets (defined below) and the Seam UI framework, you must also bundle necessary library JAR
files in the application. Three JAR files (jsf-api.jar, jsf-impl.jar, and jsf-facelets.jar) go into the myapp.war
archive’s WEB-INF/lib directory because they contain tag definitions. Facelets requires the jsf-facelets.jar
file.
Page 46 of 50
We generally add jboss-seam-debug.jar and jboss-seam.ui.jar extensions for Seam, because the former
provides the debug screen, and the latter provides some important UI extensions, as described below.
seam-debug
The Seam debug page will be available if this jar is deployed in WEB-INF/lib, along with the Facelets library, and
if you set the debug property of the init component.
seam-ui
This package contains a number of JSF custom controls that integrate with Seam. The Seam UI tags give regular
JSR UI components access to Seam managed runtime information. They help integrate Seam business and data
components more tightly with the web UI components. They can be divided into the following categories:






validation
conversation management
business process management
performance
JSF replacement tags
alternative display output
Examples of commonly used seam-ui tags are <s:decorate>, <s:convertDateTime>, <s:link>, and <s:button>
Two examples of enhancements to EL include the syntactic improvement of writing a method call as
“methodName()” rather than “methodName”, and also to allow passing in parameters to a method.
seam-text
This is primarily tools for formatting wiki text. It provides a parser and a set of converters for a simple markup
language like Zope structured text or MediaWiki markup language. We aren’t discussing this much as yet.
seam-pdf
This includes tools for generating PDF files. It in turn depends upon the iText library.
seam-mail
Handles generation of mail, communication with a mail server, and mail formatting.
Seam Tools
This is part of JBoss tools, and is documented in our file “Notes on JBoss Tools”.
Seam and MyEclipse
As of late 2008, there was not a lot of specific support for Seam within the MyEclipse environment, and we haven’t
checked since. However, there is clearly good support for JSF and Facelets, and for construction of EJB
applications, and there isn’t much extra that is needed for Seam (other than adding the library). So for the moment,
MyEclipse is neither helping nor hurting.
Appendix B: Seam Troubleshooting
These notes have been collected from a number of usages and example.
Loader constraint rule violation
You probably have the same jar at multiple points in the classpath
Page 47 of 50
Seam components file has an error
Seam is being initialized. So the problem is in the Seam initialization. Why is it that none of the Seam
components in this jar are being installed?
There are a few obvious things to look at. First, make sure that there is a seam.properties at the top
level of the EJB jar. This file can be empty. This file tells Seam to scan the jar for Seam components. That
file was present.
Next obvious thing to check is to make sure there really are proper Seam components in the EJB jar file,
with @Name annotations. This was correct. They were there.
I activated debugging output on the application. The EJB jar was being scanned and components were
being identified as components, but they were not being installed.
At this point, I couldn't get any more useful information from the Seam logs to determine why components
were not being installed. Time to use the last-ditch configuration debugging approach: start with a working
EAR file, even a simple one, and make changes to the non-working EAR file to put it in the same
configuration as the working one, and take note of when it starts working. This is a somewhat tedious
process, but I'll show a way to make it faster.
It turned out that the problem was not in the EJB jar at all. The problem was in the WAR file. jbossseam.jar should not have been in the WEB-INF/lib directory. The correct directory entries should
have been: jboss-seam-debug.jar, jboss-seam-ioc.jar, jboss-seam-remoting.jar,
jboss-seam-ui.jar, and jsf-facelets.jar. After that was fixed, all the components installed
correctly and the application works.
Cannot use JSF bindings in a Seam component
Conversational components have one minor limitation: they cannot be used to hold bindings to JSF
components. (We generally prefer not to use this feature of JSF unless absolutely necessary, since it creates
a hard dependency from application logic to the view.) On a postback request, component bindings are
updated during the Restore View phase, before the Seam conversation context has been restored.
To work around this use an event scoped component to store the component bindings and inject it into the
conversation scoped component that requires it.
@Name("grid")
@Scope(ScopeType.EVENT)
public class Grid
{
private HtmlPanelGrid htmlPanelGrid;
// getters and setters
...
}
@Name("gridEditor")
@Scope(ScopeType.CONVERSATION)
public class GridEditor
{
@In(required=false)
private Grid grid;
...
}
Alternatively, you can access the JSF component tree through the implicit uiComponent handle. The
following example accesses getRowIndex()of the UIData component which backs the data table during
iteration, it prints the current row number:
<h:dataTable id="lineItemTable" var="lineItem" value="#{orderHome.lineItems}">
Page 48 of 50
<h:column>
Row: #{uiComponent['lineItemTable'].rowIndex}
</h:column>
...
</h:dataTable>
JSF UI components are available with their client identifier in this map.
Appendix C: Performance Optimization when using Seam
One of the most useful documents that we ever found regarding Seam was about how to improve performance of a
Seam/JSF-based application that had a large number of data entry and data summarization screens (the domain was
water-quality measurements). This was from an article written by Dan Allen (author of the Seam in Action book)
and appeared in JSF Central in February 2009. See
http://www.jsfcentral.com/articles/speed_up_your_jsf_app_1.html and
http://www.jsfcentral.com/articles/speed_up_your_jsf_app_2.html.
The suggestions can be broken down as follows:
 Leverage the conversation. This means to store the relevant information there, so that it can be found.
Further, in one of the steps below, Allen suggests that rather than searching all contexts for a variable, you
search only the conversationContext.
 Make page actions run very quickly – only prefetch what is required
 Reduce the number of places where and EL expression is calling into a component with bijections. For
example if all the expression is doing is calling editable(_colIndex), but the editable method is in a class
with component and bijection overhead, there will be considerable time required to perform the bijections
on each call. Instead, move this method out to a pojo that contains only the needed data and can run fast.
This is the number one biggest problem in generating complex data screens in Seam/JSF. This is better
than the approach of bypassing interceptors, since some of them are still needed for basic state management
in the components.
 Resolve EL variables efficiently (step 1). For instance, instead of fetching reportReady as
reportManager.reportReady, you can outject reportReady into the namespace.
 Resolve EL variables efficiently (step 2). For instance, you can specify where to look, using
rendered="#{_item == conversationContext.get('itemInEditMode')}"
 Reduce the length of identifiers and CSS classnames. Basically, anything that needs to be sent from the
server to the browser will slow the application down, and when you are repeating them for a hundred cells
or more, this adds up. In the Demand Planning app (2007), we reduced the CSS class names to two chars,
and in the article Allen describes how to reduce the length of the classes and identifiers generated in Rich
Faces.

Use AJAX to refresh only a portion of the page. This works particularly well when a part of the screen is a
datatable.
The article describes that an improvement of two orders of magnitude can be achieved. We found that using these
suggestions on program SE06 (which had already been optimized somewhat, in the page actions), was able to
produce an improvement factor of 40!
Appendix D: Overview of Tutorial Programs Created


SE01 – this is a “standard” base application, derived from seam-gen, using Rich Faces and Facelets. It has
a version of entity and session packages that are what we will use going forward from early 2009. This
structure would be familiar to any programmer who has learned Seam from the seam-gen examples. The
entities are Organization and OrganizationType. The UI includes tables and sorting, using the Home
objects.
SE02 – a variation on SE01 that has a complex dialog facility for editing, in which a BusinessRule has a set
of Related BusinessRules, a set of BusinessRuleInputs, and a set of BusinessRuleOutputs. The rules are
edited one a time and saved with all of their inputs, output, etc. This proves to be a very useful example of
using RichFaces tabs, handling cascaded saves, and more. Facilities that are added in the Incra code
Page 49 of 50








beyond the Seam-Gen outputs include managing forward/back on the navigation, providing a cascade
check, and generating phrases for labels. Also contains an example of TestNG tests, and PDF production.
SE03 – is a variation on SE01 that carries out a trade management example. This has business logic to
manage a portfolio.
SE04 – is a variation on SE01 and SE02 that implements a blog-like facility. This continues our projects
that try to go outside of the “standard” look and feel or JSF and RichFaces. The important technical
features of this program are that it shows examples of 1:M and M:M relationships, plus editing of fields
that are dates, and of drop-downs. It provides an example with four different entities and one manager
class. It also shows a two-level usage model, where there are operational pages and admin pages. This is
an important change from the SE01 and SE03 series.
SE05 – activity management. This is based on supply chain models for production activities scheduled at
locations. Combination of supply-chain processes and the environmental activity models of early 2009,
similar to some of the cases in Prof Plambeck’s course at the GSB.
SE06 – reporting, import, and export. Heavily based on the Demand Planning applications of 2006-2007.
Models organizations, geographic regions, time segments, activity types, activities, and forecasts. This
program has configurable report presentations defined in the entities. It creates reports that show
organizations and activities. The import facilities are still being developed.
SE07 – menu management and navigation, plus configuration of menus per tenant and per user. This also
contains the work area for the Module, Page, and Presentation classes. The intent is that all screens in
SE07 are dynamically built and configurable, making heavy use of metadata. Some of the results of this
development will be fed back into the SE06 development.
SE08 is about forecast cells and the grid-based editor
SE09 is about attachments and uploads
SE10 is about the business process facility
To save or archive these projects, use the “clean” target in the Ant script, or manually clear the exploded-archives
directory contents, and the entire dist directory. Then they can be zipped up into something that is in the range of
14MB to 18MB.
Open Issues
When should I use the JSF-style navigation rules and when should I use the pages.xml approach? Does using the
pages.xml approach require the Drools engine? Or just the expression language? – This I think is clarified: use the
pages.xml approach, converting the JSF-style rules. You don’t need the Drools engine.
How to use the Events facility to have business logic triggered?
Page 50 of 50
Download