Welcome!

Java Authors: Maureen O'Gara, Bruce Armstrong, Liz McMillan, Walter H. Pinson, III, Yakov Werde

Related Topics: Java

Java: Article

Java J2EE Hibernate Extreme Makeover: Architecture Edition

Large-scale refactoring with Spring and Hibernate

Notice that the session factory is injected with a bean called dataSource. The dataSource bean can be injected with any class that implements the javax.sql.DataSource interface. Spring has the capability of loading different context files based on different testing scenarios. If you're running tests in an application container the dataSource bean can be defined as a container-based JNDI object.

<!-- In-Container implementation of a DataSource -->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
   <property name="jndiName"><value>jndi_datasource</value></property>
</bean>

If you're running tests out of the container the dataSource bean can be a simple JDBC connection.

<!-- Out of container implementation of a DataSource -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
<property name="driverClassName"><value>someDriverName</value></property>
<property name="url"><value>myUrl</value></property>
<property name="username"><value>user</value></property>
<property name="password"><value>password</value></property>
</bean>

By looking at this one example the power of dependency injection becomes truly apparent. One slight configuration change and we're one step closer to running our entire suite of unit tests without an application server.

It's Springtime, Get 'Outside' and Enjoy the Weather
Symptom: Code-level unit testing was taking about 10-15 minutes for one test
Root Cause: Code was completely dependent on the application server
Solution: Decoupling business logic from the EJBs allowed for out-of-container testing on every Java class

At this stage of the game the prognosis is getting better for our refactored application. We've successfully layered our architecture, applied dependency injection to move our object's dependencies into a configuration file, used AOP to audit our Web Service calls, used a Java Bean mapping framework, and replaced all the entity beans with Hibernate. One last step has to be implemented before our entire suite of unit tests can be tested out- of-container. Before Spring, EJBs were seen as the panacea for infrastructure details like security and transaction management. Most developers chose stateless session beans to handle all of their container-managed transactions. They also probably chose to store their business logic in these same beans, thus coupling them to the container with no chance of writing simple unit tests. Figure 3 offers a solution to this problem.

All of the EJB business logic has been moved into a Spring wired bean called BusinessService, which is a POJO. The EJB simply retrieves the bean out of the Spring context and calls business methods on it. In this particular example the BusinessService bean is injected with two other Spring wired beans. It's also wrapped with a custom audit interceptor as well as a Spring Hibernate interceptor. The EJB still manages the JTA transaction while the Hibernate interceptor does the Hibernate session management. The only reason that stateless EJBs weren't discarded altogether was for their RMI remoting capabilities. In future iterations we plan to remove the stateless EJBs altogether. Spring has transaction interceptors that can simulate the transactional work of a container-managed EJB.

Unit testing was made painless by using Spring's HibernateTransactionManager class. Using that class we were able to have our JUnit test cases simulate the transaction management and Hibernate session management capabilities performed in the container. Getting full transaction and Hibernate session support outside of the container lets your IDE mimic testing inside the container. Figure 4 graphically represents the unit-testing transformation.

You Reap What You Sow
At the end of the refactoring project many tangible results had been achieved:

  • Greater visibility and control in an SOA by using Spring's simple AOP mechanism for capturing auditing metrics
  • The entire code base can be tested outside of the container using Spring's dependency injection model and Hibernate for the persistence layer
  • Code is much more maintainable with a loosely coupled layered architecture
  • Refactoring is much easier with a baseline of out-of-container unit tests in place
  • Dependency injection helps immensely in mocking out external service layer calls
  • Testing becomes much easier, meaning it's more likely to happen
On any refactoring project you really do reap what you sow. Refactoring has an incredible return on investment in the short- and long-term future of your application. A word of caution before using any 'new' technologies: create a prototype application of what you want your 'end-state' architecture to look like. This prototype should be the proving grounds for all of the gory technical details and answer many hypothetical questions at two in the morning. Without our prototype, this refactoring project would have failed.

Summary - Prognosis Good
Applications that choose frameworks that allow for loose coupling can start to shed some of their J2EE baggage and leave a lot of the plumbing to tools like Spring. The days of being tightly coupled to your application server for unit testing are quickly slipping away. By using a pragmatic approach to Open Source tool selection many rewards will be instantly achieved. Applications will be more flexible and developer productivity and efficiency should increase dramatically. Not only do these tools help in decoupling, but they also tend to make applications a lot simpler by removing dependencies on J2EE containers. After having the pleasure of working on a loosely coupled flexible architecture you will wonder how any work got done before.

References

More Stories By Franz Garsombke

Franz Garsombke has been developing and architecting enterprise software solutions in Colorado for the last eleven years and is currently employed at Rally Software. Franz is a huge proponent of open source frameworks and is passionate about developing and delivering simple, quality, pragmatic applications. He is proud to be the co-founder of a Java Bean mapping framework (http://dozer.sourceforge.net) and can be reached at fgarsombke@yahoo.com or on his mountain bike.

Comments (1) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


Most Recent Comments
JDJ News Desk 10/20/05 07:06:17 PM EDT

Java J2EE Hibernate Extreme Makeover: Architecture Edition. In the past few years there has been a proliferation of frameworks that allow for lighter, faster, and loosely coupled Java projects. These frameworks not only let you decouple your Java project from the application server for unit testing, they also allow for more agile refactoring, testing, and design techniques. This article will focus on telling the story of a large-scale refactoring effort implementing Spring and Hibernate as the underlying infrastructure tools. For those living under an abacus Spring is a J2EE framework built to handle many of the plumbing issues on a typical J2EE application. Hibernate is a popular Open Source Java object/relational persistence framework.