The introductory page of the order process
The first view in our page flow is an introductory page that simply navigates to the first step in our ordering process. Notice that we use the Seam tag to render a hyperlink that includes the conversation ID as a query string parameter. This is called conversation propagation.
Seam conversation propagation using hyperlinks Seam automatically propagates the conversation during JSF form submissions using the HTTP POST method. For any GET requests (for instance, clicking on a hyperlink), we are responsible for including the current conversation ID as a request parameter to ensure that the request is handled properly. Seam provides a hyperlink control rendered by the tag that automatically includes the current conversation ID on the query string. We can also include the conversation ID as a query string parameter by nesting the Seam
The markup for the introductory screen in our order process is as follows:
<h1>Product Order Form</h1>
<h:outputText value="Welcome to our Store" />
<p>Welcome to our store. Our step-by-step forms will guide you through
the ordering process.</p>
<s:link view="/order/step1.jsf" value="Place an order" />
The following screenshot shows the introductory screen of our ordering process. Notice in the status bar of the browser window that the URL generated by the Seam JSF hyperlink control contains a query string parameter named cid with a value of one. As long as we pass this parameter from page to page, all the requests will be handled as a part of the same conversation. The conversation ID is automatically submitted during JSF postback requests. When a new conversation is started, Seam will increment the conversation ID automatically.
The customer registration screen (Step 1)
The first screen, our page flow, requires the user to provide customer information before placing an order. This view is basically identical to the example used in the Seam validation section of this article. Therefore, much of the JSF markup has been removed for simplification purposes.
Notice that the action has been hardcoded in the <a4j:commandButton> tag and corresponds to a navigation rule declaration in faces-config.xml. No additional work is required for the Seam conversation ID to be propagated to the server when the form is submitted; this happens automatically.
<h1>Step 1. Customer Registration</h1>
<a4j:form id="customerForm" styleClass="customer-form">
<a4j:commandButton value="Next Step" action="next"
The following screenshot shows the customer registration step in the online ordering page flow of our application.
The shipping information screen (Step 2)
The following screen requires the user to select a product and a shipping destination before clicking on the Next Step button. Once again, Seam conversation propagation happens automatically when the form is submitted.
The order details confirmation screen (Step 3)
The next screen requires the user to confirm the order details before submitting the order for processing. Once again, the JSF markup has been omitted for brevity. Notice that the command button invokes the submitOrder backing bean method to submit the order.
As noted earlier, this method is annotated with the Seam framework @End annotation, indicating that the long-running conversation ends after the method is invoked. When the method returns, Seam demotes the long-running conversation to a temporary conversation and destroys it after the view is rendered. Any references to conversation-scoped beans are released when the Seam conversation is destroyed, efficiently freeing up server resources in a more fine-grained way than by invalidating the session.
value="Submit Order" />
The following screenshot shows the order details confirmation screen.
The JBoss Seam framework supports the concept of concurrent conversations. An individual user may choose to open multiple browser tabs to access the same page. This scenario is not as uncommon as we might think. The user might, for example, try to rent a car for two separate trips, or place two separate orders, or book two different hotels, within the same browser session.
Conventional web applications do not support this behavior. This is because the model state needed to complete the page flow for the different use cases is typically stored in session scope. When the user switches from one tab to another in their browser, any form data that is submitted effectively overwrites the previous form data associated with the other tab. Therefore, the observable behavior of this type of user activity is a loss of session state or inconsistent results when switching between browser tabs.
Web browsers have evolved considerably over the past few years. Tabbed browsing is just one of these improvements. The Seam framework enables JSF applications to support user interaction across multiple browser tabs within the same session, significantly improving support for concurrency in Java web applications. Let's look at how Seam supports concurrent conversations by simulating a scenario where the user opens two browser tabs and performs the same workflow in each tab. The following screenshot shows a second tab opened in the browser to the introductory page of our order processing page flow. Notice once again in the status bar of the browser window that the conversation ID is now six.
When we click on this hyperlink, we will be directed to the customer registration screen in our page flow, and the backing bean used for this form will be a new instance of the OrderBean class stored in a new long-running conversation.
In the next screenshot, the user enters customer registration information for a new customer and clicks on the Next Step button. Note that we have not closed the original browser tab. That conversation is still active and we will be returning to it momentarily.
In the next screenshot, the user selects the product and shipping destination, and then clicks Next Step. The activity in the current browser tab is completely independent from the activity in the other browser tab. Remember that there are now two instances of our OrderBean class handling requests for this particular user.
Finally, we arrive at the order details confirmation step once again. The next screenshot shows your information in the second browser tab just before it is submitted for processing.
In a conventional web application, if we were to switch back to the original browser tab and refresh the page, we would see the state that is now shown in the second browser tab. In other words, the user would have overwritten the state of their original order by opening a new tab and completing the order forms in a new online ordering page flow.
Fortunately, the Seam framework was designed to support this type of concurrency, so when we switch back to the first tab and refresh the page, we see what the user expects to see: the original ordering page flow has not been modified and is in the same state as it was in, when we opened the second browser tab.
The next screenshot displays the first browser tab after we have refreshed the page. The view state is the same as it was before we started the second page flow.
To conclude our concurrent conversations, we can now submit the orders. First, we submit the order in the first tab, as shown in the following screenshot. The backing bean receives the order information, creates a success message, and redirects to the success page. When the method returns, the first long-running conversation is concluded, at which point Seam downgrades it to a temporary conversation. When the view is rendered the stateful session bean instance is destroyed along with any state it was holding for the user.
When we switch to the second tab and submit the order, our second conversation is also concluded and the order information takes a minute for processing as shown in the following screenshot.
The JBoss Seam framework enables us to support multiple concurrent requests within the same browser window without any side effects. In Seam terminology, our application supports multiple concurrent workspaces.
In this article, we looked at an example of how to use Seam conversations effectively with Ajax.
We discuss about:
- Temporary conversations in Seam conversation management
- Starting a long-running conversation in Seam conversation management
If you have read this article you may be interested to view :