| By Norman Richards | Article Rating: |
|
| February 19, 2006 12:45 PM EST | Reads: |
53,533 |
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() {
cart.addToCart(selectedProduct);
return null;
}
To get a reference to the cart, we can ask Seam to inject it using the @In annotation.
@In(create=true)
ShoppingCart cart;
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)
Search search;
public String select() {
addToCart(search.getSelectedProduct());
return null;
}
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
Seam shines at managing component links across varying contexts. We've introduced the conversation context, allowing for components that are finer-grained than the HTTP session. As a last example, we'll see how Seam can manage contextual data that's shared between users.
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">
<start-state>
<transition to="process"/>
</start-state>
<task-node name="process">
<task name="ship">
<assignment actor-id="manager"/>
</task>
<transition name="shipped" to="complete" />
</task-node>
<end-state name="complete"/>
</process-definition>
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;
@Out(scope=BUSINESS_PROCESS, required=false)float amount;
@Out(scope=BUSINESS_PROCESS, required=false)String email;
@CreateProcess(definition="OrderManagement")
public String purchase() {
// process the order
// set the orderId, amount and email fields
}
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">
<h:column>
<f:facet name="header">Order Id</f:facet>
#{task.variables['orderId']}
</h:column>
<h:column>
<f:facet name="header">Order Amount</f:facet>
<h:outputText value="#{task.variables['amount']}">
<f:convertNumber type="currency" currencySymbol="$" />
</h:outputText>
</h:column>
<h:column>
<h:column>
<h:commandLink action="#{ship.ship}">
<f:param name="taskId" value="#{task.id}"/>
</h:commandLink>
</h:column>
</h:dataTable>
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
@Name("ship")
@Interceptors(SeamInterceptor.class)
public class ShipAction
implements Ship, Serializable
{
@PersistenceContext(type=EXTENDED)
EntityManager em;
@In
Long orderId;
@BeginTask
@EndTask
public String ship() {
Order order = (Order) em.find(Order.class, orderId);
order.ship();
return "admin";
}
}
Published February 19, 2006 Reads 53,533
Copyright © 2006 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Norman Richards
Norman Richards is a JBoss developer living in Austin, Tx. He is co-author of JBoss: A Developer's Notebook and XDoclet in Action.
![]() |
SYS-CON Belgium News Desk 02/19/06 01:41:18 PM EST | |||
Web sites were originally static. Later dynamic content came about through CGI scripts paving the way for the first true Web applications. Since HTTP was entirely stateless, it became necessary to invent ways for requests to be linked together in a sequence. At first state was added to the URLs, but later the cookie concept came into being. By giving each user a special token, the server could maintain a context for each user, the HTTP session where the application can store state. As simple as it is, the HTTP session defines the entire concept of what a Web application is today. |
||||
- Kindle 2 vs Nook
- Why IBM’s Server Chief Got Busted
- Is Cloud Computing Like Teenage Sex?
- Industry Experts Discuss the State of Cloud Computing
- Performance Tuning Essentials for Java
- Confessions of a Ulitzer Addict
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- It's the Java vs. C++ Shootout Revisited!
- Cloud Computing Can Revitalize Your Career as Software Developer
- IBM Could "Reinvent" Java: Mills
- Oracle & Cloud Computing: Exclusive Q&A with SVP Richard Sarwal
- A Brief History of Cloud Computing
- Kindle 2 vs Nook
- Cloud CEOs, CTOs & SVPs to Speak at 4th International Cloud Computing Expo
- Why IBM’s Server Chief Got Busted
- Is Cloud Computing Like Teenage Sex?
- Industry Experts Discuss the State of Cloud Computing
- Performance Tuning Essentials for Java
- The Difference Between Web Hosting and Cloud Computing
- Cloud Computing Expo: Exclusive Q&A with Yahoo! SVP Cloud Computing
- Ajax in RichFaces 3.3, JSF 2 and RichFaces 4
- Confessions of a Ulitzer Addict
- My Thoughts on Ulitzer
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- A Cup of AJAX? Nay, Just Regular Java Please
- Java Developer's Journal Exclusive: 2006 "JDJ Editors' Choice" Awards
- The i-Technology Right Stuff
- JavaServer Faces (JSF) vs Struts
- Rich Internet Applications with Adobe Flex 2 and Java
- Java vs C++ "Shootout" Revisited
- Bean-Managed Persistence Using a Proxy List
- Reporting Made Easy with JasperReports and Hibernate
- Creating a Pet Store Application with JavaServer Faces, Spring, and Hibernate
- What's New in Eclipse?
- Why Do 'Cool Kids' Choose Ruby or PHP to Build Websites Instead of Java?
- i-Technology Predictions for 2007: Where's It All Headed?









































