ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Wire Hibernate Transactions in Spring

by Binildas Christudas
05/18/2005

This article is intended to show how Spring can be used to assemble components, including their transaction contexts. Connecting to a single data store from within a J2EE application is not a big hurdle. But when it comes to assembly and integration of enterprise-class components, the scenario gets complicated. A single component would be backed up by a single data store or a number of data stores. So, when we speak of assembling two or more components, we are expected to maintain the atomicity of operations done in many data stores, across components. A J2EE server provides a container for these components so that the container is able to take care of transactional atomicity and isolation across components, too. When we are not using a J2EE server, Spring helps us. Spring is based on Inversion of Control (also called Dependency Injection) for wiring not only the component services together, but also their associated transaction contexts. For the purpose of this article, we are using Hibernate as an object/relational persistence and query service.

Related Reading

Hibernate: A Developer's Notebook
By James Elliott

Assembling Component Transactions

Assume that in the enterprise component library, we already have an audit component, with service methods which can be called by clients. Later, when we want to build an order processing system, we discover the design requirement that the OrderListManager component service also needs auditing component services. The OrderListManager creates and manages orders, and hence all OrderListManager services have their own transaction attributes. When we call the audit component from within the OrderListManager service, we are in effect propagating the transaction context of OrderListManager services to audit services. Perhaps in the future, a new business service component will also need the audit component service, but the audit service will be invoked in a different transaction context. The net effect is that, even though the functionality of the audit component remains same, it can be composed with other business service functionalities, with a mix-and-match of transaction attributes to provide different run time transactional behavior.

Two separate call context flows are shown in Figure 1. In flow 1, if the client has a TX context, OrderListManager either takes part in it or starts a new TX, depending on whether the Client is in a TX or not, and also on what TX attributes are specified for OrderListManager methods. The same explanation holds true when OrderListManager service in turn invokes AuditManager methods.

Assembling Component Transactions
Figure 1. Assembling component transactions

The EJB architecture provides this flexibility by allowing the component assembler to give the correct transaction attributes declaratively. We are not exploring the alternative to declarative transaction management (called programmatic transaction control), since this involves code change to affect a different run time transactional behavior. Almost all J2EE application servers provide distributed transaction managers compliant to the Two-Phase Commit protocol as per the X/Open XA specification. Now the question is, can we avail the same functionality out of an EJB server? Spring is one of the alternative solutions here. Let us explore how Spring helps us solve our transaction-assembly problem.

Transaction Management Using Spring

We are going to look at a lightweight transaction infrastructure that can, in effect, manage component-level transaction assembling. Spring is one of the solutions here. The advantage is that we are not hooked to J2EE container services like the JNDI DataSource. The most notable point is that if we feel we need to hook this lightweight transaction infrastructure to an already-available J2EE container infrastructure, there is nothing that will stop us from doing so. It seems like we can leverage best of both worlds.

The other side of Spring lightweight transaction infrastructure is that it uses an Aspect-Oriented Programming (AOP) framework. The Spring AOP framework makes use of an AOP-enabled Spring bean factory. Transactions are demarcated by specifying transaction characteristics at the component service level, in a Spring-specific configuration file, applicationContext.xml.

<beans>

<!-- other code goes here... -->

<bean id="orderListManager"
        class="org.springframework.transaction
        .interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
        <ref local="transactionManager1"/>
</property>
<property name="target">
        <ref local="orderListManagerTarget"/>
</property>
<property name="transactionAttributes">
        <props>
                <prop key="getAllOrderList">
                        PROPAGATION_REQUIRED
                </prop>
                <prop key="getOrderList">
                        PROPAGATION_REQUIRED
                </prop>
                <prop key="createOrderList">
                        PROPAGATION_REQUIRED
                </prop>
                <prop key="addLineItem">
                   PROPAGATION_REQUIRED,
                   -com.example.exception.FacadeException
                </prop>
                <prop key="getAllLineItems">
                        PROPAGATION_REQUIRED,readOnly
                </prop>
                <prop key="queryNumberOfLineItems">
                        PROPAGATION_REQUIRED,readOnly
                </prop>
        </props>
</property>
</bean>

</beans>

Once we specify the transaction attributes at the service level, they are intercepted and interpreted by a particular implementation of the org.springframework.transaction.PlatformTransactionManager interface. This interface is given below:

public interface PlatformTransactionManager{
        TransactionStatus getTransaction
                (TransactionDefinition definition);
        void commit(TransactionStatus status);
        void rollback(TransactionStatus status);
}

Hibernate Transaction Manager

Since we have already decided that we are going to use Hibernate as the ORM tool, we need to wire in a Hibernate-specific transaction manager implementation, which is what we are going to do as the next step.

<beans>

<!-- other code goes here... -->

<bean id="transactionManager1"
        class="org.springframework.orm.hibernate.
                HibernateTransactionManager">
        <property name="sessionFactory">
                <ref local="sessionFactory1"/>
        </property>
</bean>

</beans>

Pages: 1, 2, 3

Next Pagearrow