Struts, Spring and Hibernate-Integration

Madhanasekaran

Layered architecture is the hallmark of a good web application and a layer must talk only to its adjacent layers. This makes maintenance easier and application becomes less brittle. Though there is no final word on the number of layers, an enterprise level web application should have at least the layers shown in the following figure:

For various reasons like loose coupling, prevention of vendor lock-in, different frameworks are used in different layers in enterprise level applications.

Struts is mainly used in presentation  layer and Spring in business layer or  middle tier and Hibernate or Toplink in persistence tier .Though it is possible to directly integrate Hibernate program as a plug-in  Struts  layered approach demands that business objects and methods should be eschewed from presentation layer. A light weight container like Spring which provides Transaction and other services is an ideal choice for business layer .It is observed that programming with Spring and Hibernate involves lesser amount of coding than programming with Hibernate alone as the classes in ORM module of Spring offers a lot, for Hibernate programming.

Struts is not only a  front-runner but also the fore-runner of all frame works and many of its concepts have been borrowed in other frameworks. We know the importance of struts-config.xml . Actually the Struts framework creates java objects, or, if you prefer the term beans, from the this .xml file and even their dependencies are declared there  For example in the action sub-element of action-mappings element  the attribute “name” should take the “name” attribute of  “form-bean” element earlier created. The creation of beans is not done in java code - except the helper beans which carry out business logic as they are not covered  in struts.config.xml ,being not -struts-specific .This concept of declarative management has been adopted  in Spring also-though different terms like inversion of control, dependency injection have been used. The xml file applicationContext takes care of those things .It can be said  that Spring is a POJO framework- only  plain old java classes are used, and they do  not implement special interfaces but only import them –not so in Struts.

A sample application using the above three frame works available in the web-site http://topinthetown.com with source code The application has been created by Shri.Senthil Selvan, a J2EE programmer and published in the site to enable the learners to understand the concepts involved. It has been created in Eclipse IDE with WTP plug-in and, if Sysdeo Tomcat plug-in is used, some change is required in Directory Structure. The application only displays the data retrieved from database. One may ask whether the above three frameworks are necessary for such an application. The purpose of the Application is only to show how to use the above three frameworks in your application and once one get familiarized with this one may refer to the Login application available in the web-site http://roseindia.net  We will be seeing some sample code in the parts that will follow and for the present we will confine to understanding the important concepts..

 We all know about web.xml,-the file in which all mappings between the url-patterns and servlets invoked are done.  When struts is used along with Spring, in web.xml the Spring context loader servlet(1) is loaded before the Action servlet of Struts (2), as can be seen from from the following excerpt from the web.xml file to enable the action class to invoke the context and get the beans managed by Spring framework.

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-     --(3)
hibernate.xml</param-value> ---------------------------
</context-param>

      <servlet>
<servlet-name>context</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet  -(1)

        </servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Spring context loading ends-->

<!-- Standard Action Servlet Configuration  -->
<servlet>
<servlet-name>action</servlet-name>  --------------(2)
<servlet-class>org.apache.struts.action.ActionServlet</servlet- class>                                                                  
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>

As said earlier in applicationContext .xml file  (3) above which is given as a context-param) everything-both the container services and business objects are configured as beans  and the frame work creates beans from this configuration . So a sound understanding of various elements of the above applicationContext .xml file is necessary to understand the Spring Framework.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<!-- ==== RESOURCE DEFINITIONS ==== -->

<!-- Configurer that replaces ${...} placeholders with values from a properties file -->
<!-- (in this case, JDBC-related settings for the dataSource definition below) -->
<bean id="propertyConfigurer"   ----------------------------(3)             class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location"><value>/WEB-INF/jdbc.properties</value></property>
</bean>

  <!-- Local DataSource that works in any environment -->
<!-- Note that DriverManagerDataSource does not pool; it is not intended for production -->

<bean id="dataSource"  ---------                                                       (2)
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
<property name="url"><value>${jdbc.url}</value></property>
<property name="username"><value>${jdbc.username}</value></property>
<property name="password"><value>${jdbc.password}</value></property>

            </bean>

<!-- JNDI DataSource for J2EE environments -->

<!-- Hibernate SessionFactory -->  ------------------------------------------------(1)<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="mappingResources">
<list>
<value>Book.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>

            <!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="transactionManager"   -------------------------------------------------(4)
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>

            <!-- ==== BUSINESS OBJECT DEFINITIONS === -->

<bean id="HibernateSpringDaoTarget"    ---------------------(5)
class="strutslibrary.helper.SpringHibernateDAOImpl">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>

<bean id="SpringHibernateDao"     --------------------------------------------(6)
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref local="transactionManager"/></property>
<property name="target"><ref local="HibernateSpringDaoTarget"/></property>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop
</props>
</property>
</bean>

</beans>

(1)   When we use Hibernate alone , the buildSessionFactory() method of Configuration object is invoked to obtain a session Factory object. If it is used with Spring the  SessionFactory  bean is instantiated from the LocalSessionFactoryBean of  Spring  and  hibernate properties is  given as property  of bean element Session Factory –had you used hibernate.cfg.xml file instead of hibernate.properties file in your earlier hibernate application this will look similar.

(2) datasource is configured .

(3)  a jdbc.properties file which gives replacement parameters is  used instead of hard coding the connection parameters in applicationContext.xml file.-this is optional.   
  
(4) the transaction manager provided by Spring framework is used instead of the usual session.beginTransaction() method of Hibernate

(5)business  object is created and wired to sessionFactory .

(6) shows the instantiation of TransactionProxyFactoryBean and  the wiring of  transaction manager and the business object to it  .It has  setters for a transaction manager and target which were  defined earlier . This is a convenience object that knows how to deal with declarative transaction handling and the service objects 

We know usually, Struts Action class instantiates the helper class which contains business methods.and invokes the business method contained therein. When Spring is used, the  business method is encapsulated in a class managed by Spring Framework .
In a typical Spring Application the following files are required :

1) An interface that defines the function(in our case SpringHibernateDAO)
2) An implementation that implements the function(SpringHibernateDAOimpl)
3) An xml configuration file(applicationContext.xml)
4) A client program that uses the function (in our case Struts action class)

Although it is not necessary to hide the implementation behind the interface it is recommended as a way to separate implementation from interface.

In this case Struts action class calls the business method getAllBooks()  contained in SpringHibernateDAO. For calling this method  it has to invoke the getContext() method and getbean() method of ServiceFinder as the context has to be obtained for getting the relevant bean and its methods. This is the relevant portion of the action class :

“.SpringHibernateDAO springHibernateDAO = (.SpringHibernateDAO)ServiceFinder.getContext(request).getBean("SpringHibernateDao");
List booklist = springHibernateDAO.getAllBooks();”

This is how the getContext( ) method reads:

“public static ApplicationContext getContext(HttpServletRequest httpRequest) {
return WebApplicationContextUtils.getRequiredWebApplicationContext(
httpRequest.getSession().getServletContext());”

The beans that are created and wired together in the applicationContext.xml file are 
A) container service beans
1)sessionFactory- 2) Transaction Manager  and (1)  is given as property to (2)

 B) business bean 1) HibernateSpringDaoTarget .

The above  1)Transaction Manager  and 2) HibernateSpringDaoTarget which have sessionFactory as property are given as property to the Instance of TransactionProxyFactory Bean (which is meant for simplified declarative transaction handling and thus all the beans are wired together as can be seen b elow:.

Our Java guru Shri R.S.Ramaswamy predicted  in his article  “Hibernate Explored” that appeared  in DeveloperIQ  August 2005 issue ,referring to Rod Johnson’s book “J2EE Development without EJB” as follows:

“ For he is proposing the Spring Framework as an alternative to EJB container and the idea is gaining ground,J2EE developers and students may have to reorient themselves rather abruptly to remain relevant to the industry”

Kudos to his fore-sight, his prediction has come true and you can ask him whether EJB3 will replace Spring in future, though there are people who say so, as can be seen from the following summary found in the net.


Layer

Today

                   Tomorrow

Web

             Struts

           JSF (+ Java Web Beans)

Middle

Spring-enabled POJO's

           EJB3-enabled POJO's

Persistence

           Hibernate

            JPA








}