Implementing Navigation and Pageflows with Seam



JSF style pageflows

In the last section I was explaining the need for stateful pageflows and said that it’s beneficial to know more about it. However, stateless pageflows still dominates most use cases and so let’s start our conversation with that. After you get familiar with the stateless model we will discuss the stateful option as well.

Because, Seam was built initially to bridge the gap between EJB3 and JSF and integrate the JEE frameworks together, its user interface model uses JSF by default. In fact, it improves and extends the JSF features in many areas, including navigation definition. In the latest version, 2.0.2 RC2, the framework decouples from the JSF model. The process of decoupling was initiated a couple of revision back. If Seam is used without any JSF, what so ever, it would still be possible to define stateless navigation from one page to the other using the features we will describe soon.

A stateless navigation model, by definition, is unaware of the application state while transitioning from one page to the other. It relies on mapping pages to event or action outcomes. Think of it like the case-switch clause where the particular branch to be executed is determined by the case value it matches. Stateless decision making, under elementary situations can be compared to the bifurcation of a flow on the basis of a boolean property, which can be either true or false. The decision is based only on the case value and is not directly impacted by the application state. The action or event handler can generate the outcome on the basis of the application state but that is outside the scope of the navigation rules. What the navigation rule cares about is the outcome and not how the outcome is derived.

In JSF, stateless navigation rules are defined within faces-config.xml. The listing (number 1) below shows an example of JSF navigation definition. It’s possible to use this strategy with Seam, since Seam supports JSF.

Listing 1: Example JSF navigation definition
<navigation-rule>
<from-view-id>fromStartPage.jsp</from-view-id>
<navigation-case>
<from-outcome>goAhead</from-outcome>
<to-view-id>toNextPage.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>stopNow</from-outcome>
<to-view-id>byeNow.jsp</to-view-id>
</navigation-case>
</navigation-rule>

 

JSF does not define a page action. This means that JSF triggers nothing special after it renders a page. No actions are activated or events are triggered. Seam defines page actions. Page actions and the related features can be used to define stateless pageflows and extend beyond the JSF pageflow model. Page actions are defined in a configuration file called pages.xml. So with Seam if one used JSF navigation and page flows at the same time, one would end up using two configuration files to manage the navigation rules. These would be faces-config.xml and pages.xml. However, it’s not necessary to use both the options simultaneously. Everything that can be done using the JSF navigation model can be done within pages.xml and so it may be prudent to consolidate everything right there.

Listing 2 to 4, shows snippets from the pages.xml file to illustrate Seam’s stateless navigation features. The example application in these listings is a blogging system that helps you create a new entry, edit an existing entry, preview it and publish it. It also lets you accept and respond to comments against these entries. Figure 2 depicts the application pages and features that relate to blog authoring pictorially.

flow_in_a_blog_authoring_system

 

Figure 2: Flow in a blog authoring system

 

Our first listing in this set, i.e. Listing 2, represents only the initial bifurcation between creating new document and editing existing document on the basis of the existence of the document. Listing 3 shows the flow along the new entry path while Listing 4 shows the flow along the path where we edit an existing document.


Listing 2:  Seam navigation that either redirects to 
new document creation or editing of an existing one
<page view-id="welcome.xhtml">
<navigation from-action="#{documentToManipulate.exists}">
<rule if-outcome="true">
<redirect view-id="editDocument.xhtml"/>
</rule>
<rule if-outcome="false">
<redirect view-id="createDocument.xhtml"/>
</rule>
</navigation>
</page>

Did you notice that Listing 2 invoked a method called documentToManipulate(). This method returns a boolean type return value. The return value can thus be true or false.

 

 

In Listing 3, which shows navigation for a new document creation, you will notice a separate view for the action that saves a document. In real situations you may not desire a separate view to come up on saving a document to say that the document has been saved. It would be implicit.

Listing 3: Navigation that defines the flow for creation of a new document
<page view-id="createDocument.xhtml">
<navigation from-action="#{documentManager.preview}">
<rule if-outcome="#{documentManager.preview.assetTrue}">
<redirect view-id="previewDocument.xhtml"/>
</rule>
</navigation>
<navigation from-action="#{documentManager.readyTosave}">
<rule if-outcome="yes">
<redirect view-id="saveDocument.xhtml"/>
</rule>
</page>
<page view-id="previewDocument.xhtml">
<navigation from-action="#{documentManager.creationComplete}">
<rule if-outcome="success">
<redirect view-id="publishDocument.xhtml"/>
</rule>
<rule if-outcome="failure">
<redirect view-id="editDocument.xhtml"/>
</navigation>
</page>

Continuing with Listing 4, we see the navigation rule definition for flow around editing an existing blog entry. Only two actions, i.e. preview and save, are allowed for a blog being edited. The rule here only includes the flow to the preview page. You will notice that it is identical to the rule we define for preview in a new blog entry flow.

 

Listing 4:  Navigation that defines the flow for editing an existing blog entry
<page view-id="editDocument.xhtml">
<navigation from-action="#{documentManager.preview}">
<rule if-outcome="#{documentManager.preview.assetTrue}">
<redirect view-id="previewDocument.xhtml"/>
</rule>
</navigation>
</page>

The last of the listings in this set, i.e. Listing 5, is a hypothetical definition which tries to depict the extra features that Seam allows within the navigation rule definition in pages.xml. Some of the most important of these features relate to beginning and ending conversation during navigation and passing a request parameter during redirect. We have seen method evaluation outcomes as values for an action so far. Another interesting enhancement that Seam brings to navigation is to allow arbitrary EL expression outcomes to be values of an action.

Listing 5: Additional Seam specific navigation features
<page view-id="previewDocument.xhtml">
<navigation from-action="#{documentManager.creationComplete}">
<rule if-outcome="success">
<redirect view-id="publishDocument.xhtml"/>
<end-conversation />
</rule>
<rule if-outcome="failure">
<redirect view-id="editDocument.xhtml">
<param name=”blogId” value=”#{documentManager.blogId}”/>
</redirect>
</navigation>
</page>

The stateless navigation as mentioned before is the most popular model in use. Seam’s features are adequate and flexible to implement these use cases effectively. However, with workflow and business process management application rising in number and highly interactive applications gaining in popularity, the stateful model is becoming equally important. While many options exist to manage stateful transitions, Seam is leading the way in integrating such constructs within web application frameworks.

Subtitle: 
Solving the Navigation Problem
Article Type: 
Opinion/Editorial
0
Average: 3.5 (2 votes)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)