Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Spring Web Flow 2: A boon to JSF developers

JSF 2.0 features elevate SWF 2 to more than a page-flow engine

  • Print
  • Feedback

Page 2 of 4

Workflow engines vs. BPM suites

Workflow engines differ from BPM, or business process management suites (see "What's the Difference Between Workflow and BPM?" in Resources). Spring Web Flow is a workflow engine designed exclusively for Web page navigation. JBoss jBPM, for example, is a full-fledged BPM suite that delivers workflow, Web flow (Seam page flow), BPM, and Web services orchestration (through Business Process Execution Language). Seam page flow with jPDL, a special flavor of jBPM, is conceptually and practically very close to Spring Web Flow 2. Both are designed to work with, but are not limited to, JSF technology. The main difference is that Seam is designed primarily to accommodate an EJB 3.0-based back end, while Spring Web Flow 2 aims to work inside the Spring framework. This difference makes it easy to choose between them.

Spring Web Flow aims to separate page-navigation concerns from graphical user interfaces (page templates) and view-independent business logic (Java programs). Flow hierarchy and inheritance make a Web flow defined in FDL reusable in different execution contexts. The concept of flow also introduces new object scopes into the regular Java Web application life cycle.

New scopes

Caching data objects inside a Java Web application is a common practice designed to avoid unnecessary, redundant data fetching from a back-end database and -- more important -- improve application performance. The Servlet specification offers two important object scopes: request and session. You must declare data objects displayed longer than a single request/response life cycle with the session scope, to avoid repeated database queries -- even if the data objects are referenced by only two adjacent requests. Consequently, a substantial volume of data objects stored in the session isn't garbage-collected until the session expires.

Obviously, this is an inefficient memory-management approach. As a workaround, developers using Apache MyFaces can put a custom <saveState value="#{dataObject}"/> tag on a JSP page to make that data object available just for the next request cycle. To some extent, the tag resembles the HTML <input type="hidden" value="data"> postback tag, but it stores Java objects on either the client or the server side depending on the JSF configuration.

Spring Web Flow introduces several new scopes beyond those in the Servlet and JSF specifications. The most interesting ones are view scope and flow scope. Declaring a variable (data object) in view scope is nearly equivalent to using the MyFaces <saveState> tag. Once a data object is loaded through a factory method, it remains available until the associated view state exits, no matter how many times the view (Web page) is refreshed, or a fragment of that page is reloaded (using Ajax). On the other hand, a Web flow by its nature represents a self-contained business process, in which most of the referenced data objects are no longer useful once the flow ends. Declaring variables in flow scope effectively dereferences them and makes them ready for garbage collection when the flow exits. From that perspective, flow scope is a better memory-utilization strategy than session scope, because a user might navigate multiple Web flows during a single Web session. With the help of flow scope, you can accomplish a Hibernate or Java Persistence API (JPA) long session.

Flow-managed persistence

A long session (called a conversation in JBoss Seam), in Hibernate semantics, is a type of persistence strategy. Under this strategy, you create a persistence context (Session in Hibernate, EntityManager in JPA) and reuse it for query purposes across a sequence of user requests, until all the data changes are committed to the database. This scenario is a natural fit with the Web flow concept.

A reminder

When you turn on flow-managed persistence, you should quit using Spring lazy loading filters (OpenSessionInViewFilter, OpenEntityManagerInViewFilter)<wbr>, which open and close a Hibernate Session (or JPA EntityManager) automatically upon receiving a request message and returning the response.

Flow-managed persistence in Spring Web Flow initiates a flow-scoped persistence context when the flow begins, and it flushes all the changes to the database when the flow ends (called deferred commit). You should use this approach in conjunction with an optimistic locking strategy, which you can turn on at the persistence domain-model level in Hibernate or JPA. Seam page flow persistence works essentially the same way. Setting up flow-managed persistence in Spring Web Flow is extremely easy, allowing you to concentrate on handling optimistic locking failure exceptions.

Less coding, zero JSF backing beans

Spring Web Flow's declarative or graph-oriented programming approach makes its underlying API agnostic in Web development. The default action binding in JSF binds a user action (form postback) to a backing bean's action method. In contrast, in Spring Web Flow a user action is bound to an action event, which makes the backing beans play virtually no role in page navigation.

An action event transitions one view state to another in a flow definition. During the transition, an <evaluate> tag processes the data posted back from a Web browser and prepares the data for the next view to render. Depending on the execution context, the same tag can function just as a factory method to load data for a new view to display. With Unified Expression Language (EL) or Object-Graph Navigation Language (OGNL) syntax, you can invoke a Spring bean's method in the <evaluate> tag, and the returned data object (most of the time, persistence domain data) is attached to a specific scope. Note that the POJO (plain old Java object) Spring bean is autowired (injected). Data such as a collection or an array can be configured as wrapped JSF DataModel objects to facilitate the display of HTML tabular data.

This new action-binding approach takes JSF backing beans completely out of the picture. It is consistent with the new Web Beans (JSR 299) concept proposed by the Seam technology developers. In a multilayered architecture, Web-tier Java programming becomes virtually unnecessary. (There are exceptions: you need to write helper classes to support non-POJO JSF data models such as SelectItem, or transient data objects used only for display purposes.)

As a bonus, enforcement of the Factory Method design pattern with the <evaluate> tag eliminates one of the pitfalls of JSF. A common mistake for JSF beginners is to put data-access code inside a backing bean's property getter methods. Under the hood, the JSF runtime invokes the property getter methods many times during a single request/response life cycle. As a result, the database is queried repeatedly during a single operation, which causes unbearably slow performance.

  • Print
  • Feedback

Resources

More