|
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
The button maps to the select action on the search component. (Which one? The one in the current conversation.) Seam will set the selectedProduct field, so the select() method implementation is easy, if we have a reference to correct the ShoppingCart instance.
public String select() { To get a reference to the cart, we can ask Seam to inject it using the @In annotation.
@In(create=true) The default scope for the shopping cart is session, so Seam will try to find the cart instance in the session. If there isn't a current instance, the create=true parameter asks Seam to create an instance in the session for future use. Seam can manage injection and outjection between components in differing contexts. In this case, a conversational component has injected a component from a larger context. However, we could have easily worked the other way. The buy-it action could easily have been written to act on the cart component. <h:commandButton action="#{cart.select}" value="Buy it!" /> In that case, the shopping cart could have injected the search component and retrieved the current object from it. Assuming the search component has a getSelectedProduct() method that returns the selected product, it would look like this:
@In(required=false) This is a kind of injection that other dependency injection systems just can't handle. The shopping cart, a stateful bean, can ask for the search component from a narrower context that might change from request to request. (Remember, there's one cart servicing multiple conversaton-scoped searches.) Seam ensures that any time the shopping cart is used, it will have a reference to the search component for the current context. Pushing products from the search action to the cart seems more intuitive in this case, but it's nice to know that Seam provides powerful enough mechanisms to allow the components to be written in whatever manner is most intuitive for the domain.
Business Process It's not that hard to share state between users in a Web application. One option for sharing state between multiple users in a single server is the application context. However, just like the HTTP session is too broad a context for component interaction for a single user, the application scope is also too broad for simple state communication between users. A more refined mechanism for sharing state information between multiple users is by using a business process. Think of a business process as a flow of conversations between users. A customer has a conversation with a search component that culminates in the creation of an order. Later a store employee might engage in another conversation to review or ship the order. The shared context throughout this is the order itself. Seam lets us code components to do the review and shipping acts that are as simple as the search and cart components we've already seen. Let's take a very simple order fulfillment process written using the jBPM process definition language. This simple process has one state with a ship task that has to be acted on by the store manager. Once the task is completed the process is done.
<process-definition name="OrderManagement"> This is a very trivial process, but it does illustrate the basics of process integration. Once you see how it works, it won't be hard to imagine how it can be extended to more complex processes later. Let's suppose that we've added a purchase action to the shopping cart that let the user complete the checkout. We'd like to have an instance of the business process created afterwards. With Seam, this is as easy as annotating the method with @CreateProcess.
@Out(scope=BUSINESS_PROCESS, required=false)long orderId; The @Out annotations here are on the state of the current object that we want to be shared out with the business process context. By associating the orderId with process, any component that's taking part in the process can inject the orderId and use the data. The component taking part in the action doesn't have to know where the state is coming from. It only has to know that it will get the state it needs to do the task required of it. When the process instance is created, a ship task will be created and assigned to the manager user. Seam provides several built-in components for querying tasks. The taskInstanceListForType component provides a list of a tasks by type for the current user. The following code displays a list of ship tasks for the user:
<h:dataTable value="#{taskInstanceListForType['ship']}" var="task"> The order ID and amount are displayed, followed by a button to ship the item. In the real application clicking on the button engages the store manager in a conversation with a shipping component where the manager can examine the order and either enter a tracking number or cancel the order. In this example, we'll use a much simpler component that simply changes the state of the order object.
@Stateful 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
|
||||||||||||||