4. WORK DEVELOPMENT AND RESULTS
4.1 Work Development
The JSF life cycle under the direction of Seam is more well balanced than its intrinsic counterpart. By that, I mean that in Seam’s version of the JSF life cycle, the initial request processing is just as full-featured as the postback processing. You’ve seen many of the ways in which Seam expands the activity in the initial request by applying page-oriented features. These new features include parameter mappings, front controllers, and request routing. In this section, we’re going to (quickly) step through the JSF life cycle again, this time observing the points where Seam adds its enhancements.
3.5.1 Phase listeners versus servlet filters
Seam is able to work closely with JSF thanks to the granularity offered by a phase lis-tener. Few other frameworks offer such a deep view into the execution processes. You’ll often see frameworks using servlet filters to perform such tasks, such as Spring Security.
The problem with filters is that they work at too high a level and lack the intimate knowledge of what’s going on inside the request. Without this context, it becomes dif-ficult to make the correct decision. Under some circumstances, it’s impossible for a filter to influence the execution path. Seam’s phase listener, SeamPhaseListener, is low-level enough to alter the execution flow of the life cycle as dictated by the page-oriented functionality or to get it involved in supplemental business. Let’s examine when these activities take place.
3.5.2 Stepping through the augmented life cycle
Before we get started with the revamped JSF life cycle, let me warn you that the amount of activity that happens in the Seam life cycle is daunting. Trying to cover it all on a single walkthrough would be difficult. Therefore, I’ll give you a general idea of
what happens, emphasizing key points. Think of this run-through as the highlights reel: it’s going to give you a broad overview and plenty to be excited about. Are you ready to roll the tape?
THEINITIALREQUEST, SEAM-STYLE
Once again, we’ll examine the life cycle as it processes the initial request. I promise that the story is far more interesting this time around. Table 3.2 walks through the tasks that Seam wraps around the JSF phases on the initial request.
Table 3.2 A general overview of the tasks that Seam incorporates into the JSF life cycle on an initial request (JSF phases shown in bold; horizontal line signifies transition from Restore View to Render Response)
Step Task Description
1 Initial request The life cycle begins with a GET request captured by the JSF servlet.
2 Begin JTA transaction If transaction management is enabled and JTA transactions are being used, a JTA transaction is opened.
3 Restore View On an initial request, the Restore View phase merely creates an empty component hierarchy.
4 Restore or initialize conversation
Restore the long-running conversation if requested. If there’s a prob-lem restoring it due to a timeout or concurrent access and authenti-cation isn’t required, advance to the no-conversation view. If a long-running conversation doesn’t exist, initialize a temporary conversation.
5 Handle conversation propagation
Determine from the request parameters if a long-running conversa-tion is to begin, end, be joined, or remain untouched.
6 Validate page flow If a stateful page flow is in use, it is validated to ensure the user isn’t attempting to request a page out of sequence. If the request isn’t compliant, appropriate action is taken.
7 Process page parameters
The parameters associated with this view ID are read from the request, converted, validated, and stored in the view root.
8 Enforce login, long-running conversation, and permissions
If the user must be authenticated to view this page, the nonauthenti-cated user is redirected to the login page. Once authentinonauthenti-cated, the process of rendering this page is resumed. If a long-running conver-sation is required to view this page and one doesn’t exist, the user is forwarded to the no-conversation view. If the user doesn’t have appropriate permissions to view this page, a security error is raised.
9 Apply page parameters If all validations and conversations pass, the page parameters are applied to the model via the value bindings or stored in the page con-text (no value binding).
10 Begin non-JTA transaction
If transaction management is enabled and resource-local (non-JTA) transactions are being used, the remaining response is wrapped in a resource-local transaction (through interaction with the persistence manager).
11 Emulate the Invoke Application phase
The life cycle temporarily takes on the signature of the Invoke Appli-cation phase to accommodate postback features on an initial request.
You can breathe again; the process is over. Table 3.2 doesn’t cover every last detail of the steps added by Seam in the JSF life cycle, but it comes pretty close. If you had to abbreviate this list, the most notable improvements made to the initial request are
■ Transactions are started and stopped automatically (if they are enabled).
■ Page parameters, actions, and restrictions defined in the page descriptor are applied.
12 Enforce login, long- running conversation, and permissions
The restrictions are once again applied. This step occurs twice because some execution paths will skip steps 1–9 when rendering a given view ID after a navigation event.
13 Select data model row If request was initiated by a Seam UI command component within a UIData component, advance the index of DataModel to the cor-responding row.
14 Execute page actions Each page action associated with the view ID is executed. This includes actions that are passed through a Seam UI command component. Nav-igation rules are applied after each execution. If more than one navi-gation rule is applicable, the one with the highest priority is used.
15 Commit transaction If transaction management is enabled and a transaction is active, it is committed. A new transaction is opened to prepare for the render-ing of the response.
16 Migrate JSF messages Interpolate then migrate Seam-managed FacesMessages stored in the conversation to the FacesContext, having now survived any redirects.
17 Prepare conversation switching
Conversations can be selected through a UI component. This step remembers the description and view ID for the current page. The stack must be prepared at this point in the event the life cycle is short-circuited before the Render Response phase.
18 Store conversation The conversation is stored in the session until the next request.
19 Render Response The response is rendered by reading the JSF view template and encoding it to the generated markup (typically XHTML). The UI component hierarchy is stored in either the client or the server to be restored on a postback.
20 Commit transaction If transaction management is enabled, commit the transaction that was active during the rendering of the response.
21 Prepare conversation switching
Conversations can be selected through a UI component. This step remembers the description and view ID for the current page, and updates the stack prepared prior to the Render Response phase.
22 Clean up conversation Either end the temporary conversation or update the last request time of the long-running conversation.
Table 3.2 A general overview of the tasks that Seam incorporates into the JSF life cycle on an initial request (JSF phases shown in bold; horizontal line signifies transition from Restore View to Render Response) (continued)
Step Task Description
The global transaction that Seam wraps around each request is an important part of what makes Seam applications so practical. You can safely perform persistence opera-tions in your page acopera-tions and action methods without having to worry about begin-ning and committing a transaction. Seam takes care of it for you. If you prefer to push your persistence logic to other layers, you are still able to take advantage of the global transaction since it spans the entire action method call stack. Global transactions are addressed in chapters 8, 9, and 10, which cover transactions and persistence in depth.
After seeing nearly two dozen steps on the initial request, you may be dreading the postback. Well, fear not, because there isn’t much to cover. Seam performs most of its work around the Restore View and Render Response phases.
LESSPATCHINGONPOSTBACK
This section is extremely short because a postback in the Seam life cycle is simply a combination of Seam’s page-oriented additives and the standard JSF postback mecha-nism. The most notable enhancement is that Seam wraps a transaction around the Invoke Application phase, committing the transaction once the phase is complete. This parallels how page actions are managed. Once again, Seam takes the tedium of deal-ing with transactions out of the picture until we’re absolutely ready to start fine-tundeal-ing them. One thing to watch out for is that page actions get executed on a postback, something you might not think about at first. To ensure that a page action only exe-cutes during an initial request, you can apply the following conditional logic to the page action declaration: 11
<page>
<action execute="#{actionBean.executeOnInitialRequestOnly}"
if="#{empty param['javax.faces.ViewState']}"/>
</page>
The Seam life cycle introduces quite a number of new features on top of what was already available with the JSF life cycle by hooking into its phase listener architecture.
The most blatant deficiencies in JSF are the initial request handling and the navigation
11In JSF 1.2, this check is performed by the ResponseStateManager#isPostback(FacesContext) method.
Lazy associations in the view
One of the key benefits of Seam is how it properly scopes the persistence manager (JPA EntityManager or Hibernate Session) to allow uninitialized proxies and entity associations to be traversed in the view without fear of encountering a Lazy-InitializationException (LIE). In short, they just work. In the past, developers have relied on the Open Session in View pattern to extend the lifetime of the persis-tence manager across a single request. Seam takes a smarter approach by binding the persistence manager to the conversation scope and dually wrapping a transaction around the request. In chapter 9, you learn about Seam’s conversation-scoped per-sistence manager and how it contrasts with the Open Session in View pattern.
capabilities, both of which Seam corrects, making it possible to create more sophisti-cated JSF applications. All too often, though, things go wrong. When they do, the appli-cation should handle itself just as well as it does when things go as planned. In the next section, you’ll learn that Seam helps out in this area by tacking an exception-handling facility onto JSF.