Advertisement

Extended-persistence context and application-scoped Transactions - in Seam

In this article author aims to show how Seam makes use of the extended persistent context and transaction support provided by the EJB3 container for EJB3 components and how it provide services to POJO components by its own extensions

Seam simplifies Java EE 5.0 application development by extending annotations to JSF and eliminating the artificial layer between EJB3 session beans and JSF. But the simplification of Java EE 5.0 is only a small thing in list of appreciable features of Seam. The crowning feature of Seam is its support for sophisticated application state management that is not available in any other web application framework today. That is why we call Seam the next generation web application framework and it has found its way as CDI to Java EE6.As a stateful framework it is able to offer 1) Correct usage of ORM 2) Application-scoped transaction and consequent reduced trips to database. Persistence Context is the in-memory cache of entity objects maintained by an Entity Manager (for knowing about entities and entity manager please refer to the earlier articles on JPA). In stateless frameworks the duration for which this cache is maintained is a single transaction (transaction-scoped persistence context). Seam, adopting and extending the EJB3 model, maintains this cache till the user’s action is complete. By extending the Persistence Context and storing it in a conversation, whose boundaries the developer can easily mark, Seam is able to provide easily the results, for which the developer had to toil when he uses an earlier stateless framework like Spring. We will see about the new scopes introduced by Seam, especially conversation, in a separate article. The present article aims to show how Seam makes use of the extended persistent context and transaction support provided by the EJB3 container for EJB3 components and how it provides the above services to POJO components also by its own extensions.

Correct ORM usage  Seam's unique state-management architecture allows the most sophisticated ORM integration of any web application framework. One of the objectives of an ORM is to bridge the paradigm rift between the object world and the relational world. Lazy loading plays a crucial role in this. When an ORM loads an object from the relational database, it does not necessarily load all its associated objects. Let’s look at an example. A Teacher object can be associated with a number of Student objects; each Student object can be associated with a number of Assignment objects. If the ORM framework loads all associated Student and Assignment objects when it loads a Teacher object (this is known as eager loading) it might end up loading a sizable chunk of the database into this single object. The application may only use the Teacher object and might not use the students property at all. It might just change the teacher’s name and save the object right back to the database. In this situation, Eager loading is a huge waste of resources. The ORM framework deals with this problem by lazy loading the Teacher object—that is, not loading any of the Student objects initially at all. Then, when the application calls Teacher.getStudents() explicitly, it goes back to the database to load the students list. But the problem arises when the data access layer of the web application is stateless. In the Spring framework, when an HTTP request comes in, it is dispatched to Spring’s Hibernate-integration template and Hibernate lazy-loads the Teacher object, which is returned to the web presentation layer. Since Spring is a stateless framework, it destroys the persistence context when the Teacher object is passed back to the presentation layer, in preparation for the next stateless data query (transaction-scoped persistence). Now, if the web page displays a list of student names associated with the teacher, the web presentation layer will need to lazy-load the students list as it renders the page. But here is the problem. As far as Spring is concerned, the data loading is done. If the web presentation layer attempts to lazy-load associated objects after Spring returns, an exception will be thrown. In fact, this lazy loading exception is one of the most often encountered Hibernate exceptions of all time. Seam is the culmination of the attempts of the Hibernate team to put the ORM to correct usage and avoid this exception.

Effect of absence of construct for optimistic transaction processing (OPT) in Spring
Stateless architectures have depleted the persistence manager of its true value—to monitor a set of managed entities and transparently migrate changes made to them to the database. The state management architecture of Seam was designed to solve problems associated with (OTP). OTP assumes that multiple transactions can complete without affecting each other, and that therefore transactions can proceed without locking the data resources that they affect. Before committing, each transaction verifies that no other transaction has modified its data. If the check reveals conflicting modifications, the committing transaction rolls back. Online applications always use optimistic transactions. So Hibernate was designed to support the idea of a persistence context, which spanned an optimistic transaction. Persistent context is the in-memory cache of all entities an entity manager manages. Persistence scope is the duration for which it is so managed. Unfortunately, the so-called "stateless" architectures that preceded Seam and EJB 3.0 had no construct for representing an optimistic transaction. Instead, these architectures provided persistence contexts scoped to the atomic transaction. In such cases once the transaction is over the persistence manager is closed and the entities it manages become detached as shown in Figure-1.When another persistent manager is created it can invoke the merge() and persist the detached entities but when un-fetched associations are accessed LazyInitializationExceptions are thrown. In the absence of a construct for OTP, Spring could not support lazy loading or automatic dirty checking, two valuable features of ORM.




Open session in view 
  
The answer of the users of Hibernate to the detached entities or lazy loading problem is open session in view. The data layer is not allowed to close the session and a filter is entrusted with the task of closing the session after the all the request is carried out. This pattern is implemented as a single transaction, which spans the entire request. The problem with this fix is that a filter is too far removed from the application to know what it’s doing. Complications also arise because now the Session has two masters, the application framework and the filter, which may not always be in agreement. The application doesn’t know whether the database writes succeeded or failed until after the view is rendered

Extended persistent context

Java EE5 introduced the concept of an extended persistence context by marrying JPA and stateful session beans, both residents of the EJB 3 specification. Transactions are enabled by default for all EJB3 session bean methods in an EJB3 application. You have the choice of using a transactional or extended persistence context, defined by the annotation’s type attribute. The transaction-scoped persistence context, which is the default type, binds the EntityManager to the scope of the JTA transaction. An extended persistence context, on the other hand, keeps the EntityManager open for the lifetime of the SFSB. As already said persistence context is the in-memory cache of entity instances managed by an entity manager and hence the extended persistence context confers certain benefits. They are:

? Allows safe lazy loading of entity associations and uninitialized proxies
? Eliminates merging to synchronize detached entity instances to the database
? Ensures only one object reference exists for a given entity identifier
? Works in conjunction with optimistic locking to support long-lived units of work.

 But this is not available for a non-EJB environment.

Strategies of Seam

Seam has both adopted the EJB3 model of a stateful component (stateful session bean) with an extended persistence context scoped to the lifetime of the component. But the component is stored in the stateful container “conversation” instead of HTTPSession. We will see why conversation is a better choice in the next article. Here is the extract from HotelBookingAction.java in the booking application in the examples folder of seam distribution:

@Stateful
@Name("hotelBooking")
@Restrict("#{identity.loggedIn}")
public class HotelBookingAction implements HotelBooking
{

@PersistenceContext(type=EXTENDED) //-------------1)
   private EntityManager em;

………………
   @Begin                  //--------------------------2)
public void selectHotel(Hotel selectedHotel)
{
hotel = em.merge(selectedHotel);
}
public void bookHotel()
{     
booking = new Booking(hotel, user);
Calendar calendar = Calendar.getInstance();
booking.setCheckinDate( calendar.getTime() );
calendar.add(Calendar.DAY_OF_MONTH, 1);
booking.setCheckoutDate( calendar.getTime() );
   }  
…….
   @End   //----------------------------------------- 2)
public void confirm()
{
em.persist(booking);
facesMessages.add("Thank you, #{user.name}, your confimation number for #{hotel.name} is #{booking.id}");
log.info("New booking: #{booking.id} for #{user.username}");
events.raiseTransactionSuccessEvent("bookingConfirmed");
}  
@End
public void cancel() {}
@Remove
public void destroy() {}

1) @PersistenceContext annotation injects  container managed Entity Manager for the duration of the life of a stateful session beans .
 
2) A long running conversation  is started with @Begin annoation and is transitioned into a temporary conversation with @End annotation. By default, the database flush mode is set to AUTO. What is flush()  method of Entity Manager is doing? EntityManager operations like persist, merge, and remove do not cause immediate database changes. Instead, these operations are postponed until the EntityManager is flushed. The true motivation for doing things this way is performance optimization. Batching SQL as much as possible instead of flooding the database with a bunch of frivolous requests saves a lot of communication overhead and avoids unnecessarily tying down the database. When the flush mode is AUTO, the Entity-Manager performs a flush operation automatically as needed. In general, this occurs at the end of a transaction for transaction-scoped EntityManagers or when the persistence context is closed for application-managed or extended scope EntityManagers. Hence the database changes will be flushed at the end of the execution of confirm() and the extended persistence context will be closed.Then only the stateful session bean is destroyed.

II The Seam has extended the above model for more complex applications, with many loosely-interacting components in each conversation, where propagation of the persistence context across components is required. In this, Seam takes full control of the extended persistence context by creating its own persistence manager and storing it directly in the conversation. The seam-managed persistence context and transaction support can be used for both EJB and non-EJB environments. An application in the examples is available in jpa application. The extract from the same HotelBookingAction.java from this application is given below:

@Name("hotelBooking")
public class HotelBookingAction
{
   @In
   private EntityManager em;

You can see that it is only a POJO and seam-managed persistent context is injected. The container will bootstrap a container-managed persistence context from persistence-unit but to bootstrap a seam managed persistent context certain extra configuration in component.xml is necessary. You can see the following lines in the components.xml of this application.

<transaction:entity-transaction entity-manager="#{em}"/> //----------3)
………..
<persistence:managed-persistence-context name="em" auto-create="true"  //-----1)
       entity-manager-factory="#{bookingDatabase}" persistence-unit-jndi-  name="java:/bookingEntityManagerFactory"/>   //………………………………….2)

1) When you declare the Seam-managed persistence context, you must supply a name and a reference to a entity  manager factory. By setting auto-create = true , you can inject these components using an @In annotation without having to supply the create attribute.

2) A reference to the persistent unit is given through its jndi name.

You can see in META-INF/persistence.xml the following line configuring the jndi name of the persistent unit.

<property name="jboss.entity.manager.factory.jndi.name" value="java:/bookingEntityManagerFactory"/>

3) Transaction is entity transaction and the entity manager referenced is the one created in step 1.
  
You can compare the persistent.xml files the two applications. In the first <jta-data-source > is specified, as the Transaction type is JTA for container-managed transactions and in the second <non-jta-data-source> is specified, as the transaction type is "RESOURCE_LOCAL"> for seam-managed transactions. But the provider is the same ie hibernate in both cases but you can choose to configure and use another provider.

     Transactions in Seam Transactions, as you know, are important aspect of database operations. A transaction is a grouping of tasks that must be processed as an inseparable unit. This means every task that is part of the transaction must succeed in order for the transaction to succeed. If any of the tasks fail, the transaction fails as well. When you pay your telephone bill through bank, your account will be debited and the telephone provider’s account will be credited .If one of the tasks in this operation fail the other task is also not carried out. You know in EJB there are two types of transactions. Container Managed Transactions (CMT) and Bean Managed Transactions. The first is to declaratively manage transactions; this can be done through annotations or the deployment descriptor. On the other hand, bean-managed transaction (BMT) requires you to explicitly manage transactions programmatically. In Seam you can use either CMT or Seam Managed Transactions (SMT) and both are declaratively managed through xml configuration files and annotations. Transactions are enabled by default for all EJB3 session bean methods in an EJB3 application. Then how the transaction support of Seam comes into picture for EJB3 applcations? You can see  in the /resources/WEB-INF/component.xml the following line:<transaction:ejb-transaction />. In other words in an EJB3 application, Seam indirectly manages the extended persistence context and co-ordinates and fine tunes transaction support provided by the EJB container.

Seam-managed transactions are enabled by default for POJOs also. You can disable this behavior by placing the following in your components.xml:
<core:init transaction-management-enabled="false"/>
<transaction:no-transaction />

In EJB3, by default all session bean methods are REQUIRED to participate in a transaction. REQUIRED indicates that if the calling client is associated with a transaction, your bean will participate in that transaction. If the calling client is not associated with a transaction, the container will begin a new transaction and attempt to commit that transaction on completion of method execution. You can modify this default behavior through @TransactionAttribute annotation .Methods of a Seam POJO are also managed by the Seam transaction manager by default. POJO components have @Transactional (SUPPORTS) behavior by default, but this behavior can be customized through use of the @Transactional annotation. The default Transaction Propagation Type is enabled if the @Transactional annotation is not placed on a POJO component. In this default behavior, if the calling client is associated with a transaction, the POJO will participate in that transaction; otherwise, no transaction is started. The default behavior ensures that both EJB’s and POJO’s methods execute within the context of a transaction and atomicity is ensured in a request even across loosely coupled components. The additional transactional attributes supported by Seam simply provide a finer granularity of control for more complex transactional scenarios regardless of application environment.

The seam managed transaction used with seam-managed persistent context becomes superior to the transaction support provided by earlier frame-works as explained above. Three services comprise of Seam’s transaction support (all optional):
1) Global transactions
2) Transaction abstraction layer
3) Application transactions

Global transactions
When used with JSF, the Seam transaction manager runs two transactions for each web request/response cycle. The first transaction spans from the start of the RESTORE_VIEW phase to the end of the INVOKE_APPLICATION phase. The second transaction is started prior to the RENDER_RESPONSE.

Transaction abstraction layer

 Seam moulds this abstraction out of the standard Java EE transaction API by extending JTA’s UserTransaction interface. Calls to this interface are delegated to the underlying transaction manager. You can also configure any other transaction manager to work with Seam. That means you can take advantage of Seam’s transaction management without committing to yet another transaction platform. Seam also provides a number of convenience methods that ease the task of managing the transaction from the application code.   

Application transactions

Seam works with the Seam-managed persistence context and Hibernate to facilitate application transactions. In an application transaction, flushing the persistence context is deferred until the final step of the use case and executed within a database transaction. An application transaction relies on optimistic locking. A Seam-managed persistence context is quite simple to configure in your components.xml file as shown above. Once we have configured a persistence context scoped to the conversation, the final step is configuring manual flushing. JPA does not define the concept of manual flushing. As mentioned earlier, by default, a JPA persistence-context is configured for AUTO commit mode. This means that each time a transactional method is executed, any updates to an entity during execution will be persisted once the transaction is successfully committed. This is an issue, since we only want to commit entity changes only when the conversation completes. We can achieve this by manually flushing the persistence context. Setting the flushMode attribute to MANUAL stops the transaction manager from flushing any updates to the database at the end of each transaction. The database updates are cached in the persistence scope throughout the entire conversation. Then, in the @End method, you call EntityManager.flush() to send the updates to the database all at once. You can set the default flush mode globally in the component descriptor:

<core:manager default-flush-mode="MANUAL" .../>

To know more about this, you can refer to chapter 9 of the book “Seam in Action” by Dan Allen or Chapter 11 of the book “Seam Framework” by Michael J.Huan and others.

Conclusion

As we saw earlier, Seam being a stateful framework, solved once and for all the dreaded lazy loading problem. By default, a Seam component keeps the persistence context valid from the time when an HTTP request is submitted to the time when the response page is fully rendered. Seam can do that because it is stateful and remembers which request/response cycle or HTTP session it is associated with. So, in a Seam application we can pass entity objects (i.e., EJB3 entity beans) directly across the business layer and the presentation layer without the need to wrap them in DTOs. Those are significant productivity gains from the simple fact that Seam finally allows us to use ORM the “correct” way. A nice side effect of keeping the persistence context valid beyond a single stateless method call is the reduction of database roundtrips. For instance, a shopping cart application can save every item of an order into the database as the user adds products into the cart. But then, if the user abandons the shopping cart, the application would have to clean up the database. It would be much better if the orders were never saved into the database in the first place. Seam follows this model. The Seam application saves orders in a batch when the user checks out the shopping cart. Before Seam, application developers had to develop sophisticated caching mechanisms to hold the database updates for each user session in memory. With the extended persistence context in Seam, we get all that for free! A stateful component can stay valid across several web pages (such as a web wizard or a shopping cart) through a long-running conversation in Seam. The component only dirty-checks objects and flushes changes to the database from its persistence context at the end of the conversation. We will see more about this conversation in future.

For more information on Extended-Persistence context and application-scoped transaction in seam you can contact the author from the following URL. sekaran.madhan@gmail.com








Added on January 25, 2012 Comment

Comments

#1

Prathamesh commented on March 15, 2013 at 11:30 p.m.

Fantastic! Simple words with clarity.

Post a comment