 |
Application Transaction
|
|
 |
The standard JTA transaction is thread-based. The transaction has to commit or rollback at the end of a thread. At the end of the thread, the transaction is committed; the data changes are flushed to the database; and the persistence context for the EntityManager is destroyed. For some web applications, this "one thread" limitation is an inconvenience. For instance, let's consider a shopping cart application. The user needs to go through multiple web pages: to select the products, to enter the credit card information, to enter shipping address, to review the final cost, and then finally to finish the entire transaction. Each page submission is processed by a separate thread on the server and the order should only be committed to the database after the last page.
In EJB 3.0, there is an option to cache all database updates from multiple method calls (i.e., multiple threads) in the EntityManager , and only commit the changes in a batch when the application finishes a logical session (e.g., at the checkout time of a shopping cart). In this trail, we will cover how to mimic such a multi-page application transaction.
|
|
|
 |
The sample application in this trail is a simple variation of the "currency exchange rate update" example for the investment calculator we have seen earlier in the previous trail. After you submit a new currency exchange rate, the application updates all the calculation records in the entity bean objects but it does not flush the changes to the database yet. The application then displays another page asking you whether to update the timestamp of those records. If you choose "yes", the timestamp attribute of the bean objects are also updated and all the changes are flushed to the database in a single batch.
|
|
|
 |
To make the application transaction work, you first need to specify the type attribute of the the @PersistenceContext injection annotation as PersistenceContextType.EXTENDED . It tells the container that the EntityManager object maintains its persistence context (i.e., the entity bean objects it manages) across multiple threads or method calls.
@Stateful
public class ApptransCalculator implements Calculator, Serializable {
@PersistenceContext(
type=PersistenceContextType.EXTENDED
)
protected EntityManager em;
// ... ...
}
|
|
|
 |
Then, we tell the JTA transaction manager NOT to commit any updates to the database at the end of each thread. We do this by giving each database related method the NOT_SUPPORTED transactional attribute. The EntityManager should only update the database when the stateful session is destroyed. Recall that we can destroy a stateful session bean by calling the @Remove tagged method. So, we explicitly call the EntityManager.flush() method in the @Remove method to send in all updates to the database.
@Stateful
public class ApptransCalculator implements Calculator, Serializable {
// ... ...
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void updateExchangeRate (double newrate) {
// ... ...
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void updateTimestamp () {
// ... ...
}
@Remove
public void checkout() throws Exception {
em.flush ()
}
}
|
|
|
 |
Server
Client
- calculator.jsp: The client JSP that performs the first stage of the update transaction
- check.jsp: The client JSP that performs the second stage of the update transaction
|
|
|
 |
In this trail, you learned how to use long lived EntityManager object for multi-page application transactions, such as those in a shopping cart application. In the next trail, we will discuss another type of container service for managed objects and methods: security services.
|
|
|