|
SYS-CON Magazines
|
Top Linux Links You Must Click On
Feature Seam: The Next Step in the Evolution of Web Applications
A powerful new application framework for managing contextual components
By: Norman Richards
Feb. 19, 2006 12:45 PM
To get a better feel for it, let's add some additional functions to the search component and see exactly how the conversation works.
static final int PAGE_SIZE = 10; The changes add a little bit of extra state to the search component, namely the concept of a current page in the search results. The loadProducts() method now uses the current page number to load only a single page of results. An extra product is loaded as a test to see if there are are additional results available in the database. That provides enough information for the isFirstPage() and isLastPage() methods to determine whether or not the current page is either the first or last page of the results. Finally, SearchAction now provides nextPage() and prevPage() action methods to alter the current state of the component. These methods work by changing the current page number and reloading the products list. The new products list is pushed out to the view to be displayed. The listing below shows all the required changes to the view.
<h:form> The output is wrapped in a form that contains buttons linking to the prevPage() and nextPage() actions on the search component. Seam components are directly usable from a view by name. Seam will make sure that the appropriate instance for the current context (the current conversation, in this case) is available. Let's look more closely at this. To display the products list on the page, Seam locates the search component, which the products factory, and loads the data. The loadProducts() method is annotated with @Begin, which hints to Seam that the current conversation (the one started when the page was first loaded) is a long-running conversation and should be kept around (without this hint, Seam would assume the conversation would expire at the end of the request and remove the conversation, along with any components in that scope). With a conversation in place, the previous and next buttons automatically link to the action methods on the same instance we're talking to now. As long as the user continues to click through these actions, the conversation is maintained and the users sees the appropriate state. However, if the user loads the page again or accesses the page in another tab or window, Seam will interpret this as a request for a new conversation and create a new stateful search component to service this conversation. Seam can maintain any number of concurrent conversations with a user, letting the user browse through multiple sets of search results without ever confusing the data between conversations as might happen if the search results were naively put in the HTTP session. This is an amazingly powerful concept considering the component didn't have to be specially coded to be able to do it. The search component simply implements the logic required to maintain its own state. Seam takes care of controlling the visibility and lifecycle of the instances. To complete the example and show a few extra features of Seam, we'll add the ability to select specific products and add them to a shopping cart. We'll start with a basic shopping cart component.
@Stateful It's another stateful session bean. The state of the cart is the list of products in the cart, and the bean provides a method for adding a product to the cart. Just like the search component, the cart is a simple POJO concerned only about managing its state and providing useful functions to the application. The shopping cart is a session-scoped bean. No matter how many simultaneous searches a user does, items should be added to the same cart instance. Session scope matches this perfectly, so we use the @Scope annotation to override Seam's default conversational scope for stateful components. We're done with the shopping cart, so now we'll head back to the search component and its UI view. We need a simple way to operate on items in the products list. JSF provides a DataModel interface that can be used in conjunction with the dataTable tag to provide a concept of selecting an individual row of the table. Using it, however, would couple our application to the UI and move the search component more towards being a UI component than an application component. Seam provides the solution here by providing UI wrapper annotations that let you construct UI components out of internal state. By replacing the @Out tag with the @DataModel tag on the products list, Seam will make sure that the UI sees a proper JSF DataModel instead of a simple list.
@DataModel A DataModel can have a selected item, and Seam can inject the selected item back into the search component using the @DataModelSelection annotation. Whenever an action is done on a row in the products dataTable, the selectedProduct value will be set accordingly.
@DataModelSelection The dataTable can be easily updated with a button to add a specific item to the cart. The following code adds a "Buy it!" button on each row of the table.
<h:dataTable value="#{products}" var="prod"> Reader Feedback: Page 1 of 1
Subscribe to our RSS feeds now and receive the next article instantly!
Subscribe to the World's Most Powerful Newsletters
|
||||||||||||||