Wire Hibernate Transactions in Spring
Pages: 1, 2, 3
Running The Demo
For running the test cases, a JUnit test class,
OrderListManagerTest, is provided within
myusers\test\com\example\service. To execute it, run the
following command from the command prompt where we built the
application:
CATALINA_HOME\bin\ant test -Dtestcase=OrderListManager
The test case is divided into two main sections: the first section creates an order consisting of two line items, and then links the two line items to the order. This is shown below, and will run successfully:
OrderList orderList1 = new OrderList();
Long orderId1 = orderListManager.
createOrderList(orderList1);
log("Created OrderList with id '"
+ orderId1 + "'...");
orderListManager.addLineItem(orderId1,lineItem1);
orderListManager.addLineItem(orderId1,lineItem2);
The next section performs a similar action, but this time we are trying to add three line items to the order, which will generate an exception:
OrderList orderList2 = new OrderList();
Long orderId2 = orderListManager.
createOrderList(orderList2);
log("Created OrderList with id '"
+ orderId2 + "'...");
orderListManager.addLineItem(orderId2,lineItem3);
orderListManager.addLineItem(orderId2,lineItem4);
//We know, we will have an exception here,
still want to proceed
try{
orderListManager.addLineItem
(orderId2,lineItem5);
}
catch(FacadeException facadeException){
log("ERROR : " + facadeException.getMessage());
}
The console print out is shown in Figure 5:

Figure 5. Client-side console output
We have created Order1, and added two line items with Line Item IDs 1 and 2 to it. Then we created Order2, and tried to add three items. Adding the first two line items (with Line Item IDs 3 and 4) was successful, but Figure 5 shows that when we tried to add a third item (with Line Item ID 5) to Order2, the business method met an exception. Hence, the business method TX is rolled back, and no Line Item with Line Item ID 5 is persisted in the database. This can be validated as shown in Figure 6 and Figure 7, which is possible by executing the following command from the console:
CATALINA_HOME\bin\ant browse1

Figure 6. Orders created in the appfuse1 database

Figure 7. Line items created in the appfuse1 database
The next, and most important, part of the demonstration shows
that orders and line items are persisted in appfuse1 database,
whereas audit objects are persisted in appfuse2 database. In effect, the
service methods in OrderListManager talk to multiple
databases. Open up the appfuse2 database to see the
audit trail, as shown below:
CATALINA_HOME\bin\ant browse2
Figure 8. Audit trail created in the appfuse2 database, with entry for
failed TX
The last row in Figure 8 needs special attention. The RESOURCE
column says "this row corresponds to LineItem5." But if we go back
to Figure 7, there is no line item corresponding to LineItem5. Has
something gone wrong here? In fact, everything worked perfectly,
and this extra row in Figure 7 is what this whole article has been
about. We will now discuss what has happened here.
We know that addLineItem() method has
PROPAGATION_REQUIRED and the log() method has
PROPAGATION_REQUIRES_NEW. Further,
addLineItem() internally calls the log()
method. So when we tried to add a third line item to Order2, an
exception is raised (as per our business rule), which will roll
back both the creation of this line item and the linking of this
line item with Order2. But, since a call to log() is
also made from within addLineItem(), and since
log() has the PROPAGATION_REQUIRES_NEW TX
attribute, the rolling back of addLineItem() will not
roll back log(), since log() happens in a
new TX.
Let us now make a change in the TX attribute of
log(). Instead of
PROPAGATION_REQUIRES_NEW, change the TX attribute to
PROPAGATION_SUPPORTS. The
PROPAGATION_SUPPORTS attribute allows the service
method to run in a client TX, if the client has a TX context,
otherwise the method runs with no TX at all. You may have to
reinstall the application so that the already-available data in
the databases are automatically flushed. To reinstall, follow step
12 in the "Setting up the Demo Environment" section above.
If we repeat the run, we will experience a slightly different
behavior this time. This time, we will still get an exception
scenario when we try to add a third line item to Order 2. This will
roll back the transaction that attempts to add the third line item.
This method, in turn, calls the method log(). But since
log() has a TX attribute of
PROPAGATION_SUPPORTS, log() will be
invoked in the same TX context as that of
addLineItem() method. Since addLineItem()
rolls back, the log() also rolls back, leaving no
audit trace for the rolled-back TX. So there is no audit trail
entry in Figure 9, corresponding to the failed TX!
Figure 9. Audit trail created in the appfuse2 database, without entry for
failed TX
The only change we have done for this different transaction behavior is that we changed the TX attribute in the Spring configuration, as shown below:
<bean id="auditManager"
class="org.springframework.transaction.
interceptor.TransactionProxyFactoryBean">
<property name="transactionAttributes">
<props>
<!-- prop key="log">
PROPAGATION_REQUIRES_NEW
</prop -->
<prop key="log">
PROPAGATION_SUPPORTS
</prop>
</props>
</property>
</bean>
This is the effect of declarative transaction management, which we have been leveraging since the inception of EJB. But we know that we need a high-end application server to host our EJB components. Now we have seen that similar results can be attained even without an EJB server, using Spring.
Summary
This article throws light onto one of the powerful combinations in the J2EE world: Spring and Hibernate. By leveraging the capabilities of both, we have alternate technology options for Container-Managed Persistence (CMP), Container-Managed Relationships (CMR), and Declarative Transaction Management. Even though Spring wasn't conceived as an alternative to EJB, it provides features, such as declarative transaction management for plain Java objects, that enable users to dispense with EJB in many projects.
It is not the aim of this article to find out an alternative to EJB, but we are trying to find out the best available technology options for the problems at hand. Hence, we need to explore further capabilities of the lightweight combination of Spring and Hibernate, and this is left as a subject for further exploration for the reader.
Resources
- Sample code for this article
- www.springframework.org
- www.hibernate.org
- Spring Live reference book
- Better, Faster, Lighter Java reference book
- Hibernate: A Developer's Notebook reference book
- Expert One-on-One J2EE Development without EJB, by Rod Johnson and Juergen Hoeller
- Hibernate/Spring/Middlegen/XDoclet tutorial
- Hibernate-Spring
Binildas Christudas is a Senior Technical Architect at Communication Service Providers Practice (CSP) of Infosys, and is a Sun Microsystems Certified Enterprise Architect and a Microsoft Certified Professional.
Return to ONJava.com.
-
JUnit Test AOP?
2005-05-25 21:17:33 dslevine [View]
-
Use JOTM for JTA
2005-05-24 00:23:45 sethladd1 [View]
-
You need a JTA!?!
2005-05-20 03:41:17 guypardon [View]
-
Hibernate Transaction in Spring
2005-05-19 11:23:23 ilim72 [View]
-
Hibernate Transaction in Spring
2008-09-04 07:59:16 Cna8585 [View]