Best approach for integrating spring and hibernate
===

I was going to integrate hibernate and struts2 Please advise which is the best approach to that , I was thinking that in Struts2, there are no official plugins to integrate the Hibernate framework. But, you can workaround with the following steps :

1) Register a custom ServletContextListener.
2) In the ServletContextListener class, initialize the Hibernate session and store it into the servlet context.
3) In action class, get the Hibernate session from the servlet context, and perform the Hibernate task as normal.

Please advise that my approach of servlet context for initalizing hibernate session facctory is ok or there can be othe best approch also . here is the snapshot of the project.

Here is the piece of code..


The model class...

    package com.mkyong.customer.model;
     
    import java.util.Date;
     
    public class Customer implements java.io.Serializable {
     
    	private Long customerId;
    	private String name;
    	private String address;
    	private Date createdDate;
     
    	//getter and setter methods
    }
the hbm mapping file ..


    <hibernate-mapping>
        <class name="com.mkyong.customer.model.Customer" 
    	table="customer" catalog="mkyong">
     
            <id name="customerId" type="java.lang.Long">
                <column name="CUSTOMER_ID" />
                <generator class="identity" />
            </id>
            <property name="name" type="string">
                <column name="NAME" length="45" not-null="true" />
            </property>
            <property name="address" type="string">
                <column name="ADDRESS" not-null="true" />
            </property>
            <property name="createdDate" type="timestamp">
                <column name="CREATED_DATE" length="19" not-null="true" />
            </property>
        </class>
    </hibernate-mapping>

The configuration file is...


    <hibernate-configuration>
      <session-factory>
        <property name="hibernate.bytecode.use_reflection_optimizer">false</property>
        <property name="hibernate.connection.password">password</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mkyong</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        <property name="use_sql_comments">false</property>
        <mapping resource="com/mkyong/customer/hibernate/Customer.hbm.xml" />
      </session-factory>
    </hibernate-configuration>

The listener class...

    package com.mkyong.listener;
     
    import java.net.URL;
     
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
     
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
     
    public class HibernateListener implements ServletContextListener{
     
        private Configuration config;
        private SessionFactory factory;
        private String path = "/hibernate.cfg.xml";
        private static Class clazz = HibernateListener.class;
     
        public static final String KEY_NAME = clazz.getName();
     
    	public void contextDestroyed(ServletContextEvent event) {
    	  //
    	}
     
    	public void contextInitialized(ServletContextEvent event) {
     
    	 try { 
    	        URL url = HibernateListener.class.getResource(path);
    	        config = new Configuration().configure(url);
    	        factory = config.buildSessionFactory();
     
    	        //save the Hibernate session factory into serlvet context
    	        event.getServletContext().setAttribute(KEY_NAME, factory);
    	  } catch (Exception e) {
    	         System.out.println(e.getMessage());
    	   }
    	}
    }
and the web.xml is...


    web-app>
      <display-name>Struts 2 Web Application</display-name>
     
      <filter>
    	<filter-name>struts2</filter-name>
    	<filter-class>
    	  org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
    	</filter-class>
      </filter>
     
      <filter-mapping>
    	<filter-name>struts2</filter-name>
    	<url-pattern>/*</url-pattern>
      </filter-mapping>
     
      <listener>
        <listener-class>
    	  com.mkyong.listener.HibernateListener
        </listener-class>
      </listener>
     
    </web-app>

finally the action class..


    ackage com.mkyong.customer.action;
     
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
     
    import org.apache.struts2.ServletActionContext;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
     
    import com.mkyong.customer.model.Customer;
    import com.mkyong.listener.HibernateListener;
    import com.opensymphony.xwork2.ActionSupport;
    import com.opensymphony.xwork2.ModelDriven;
     
    public class CustomerAction extends ActionSupport 
    	implements ModelDriven{
     
    	Customer customer = new Customer();
    	List<Customer> customerList = new ArrayList<Customer>();
     
    	public String execute() throws Exception {
    		return SUCCESS;
    	}
     
    	public Object getModel() {
    		return customer;
    	}
     
    	public List<Customer> getCustomerList() {
    		return customerList;
    	}
     
    	public void setCustomerList(List<Customer> customerList) {
    		this.customerList = customerList;
    	}
     
    	//save customer
    	public String addCustomer() throws Exception{
     
    		//get hibernate session from the servlet context
    		SessionFactory sessionFactory = 
    	         (SessionFactory) ServletActionContext.getServletContext()
                         .getAttribute(HibernateListener.KEY_NAME);
     
    		Session session = sessionFactory.openSession();
     
    		//save it
    		customer.setCreatedDate(new Date());
     
    		session.beginTransaction();
    		session.save(customer);
    		session.getTransaction().commit();
     
    		//reload the customer list
    		customerList = null;
    		customerList = session.createQuery("from Customer").list();
     
    		return SUCCESS;
     
    	}
     
    	//list all customers
    	public String listCustomer() throws Exception{
     
    		//get hibernate session from the servlet context
    		SessionFactory sessionFactory = 
    	         (SessionFactory) ServletActionContext.getServletContext()
                         .getAttribute(HibernateListener.KEY_NAME);
     
    		Session session = sessionFactory.openSession();
     
    		customerList = session.createQuery("from Customer").list();
     
    		return SUCCESS;
     
    	}	
    }

the jsp page...

    <%@ taglib prefix="s" uri="/struts-tags" %>
    <html>
    <head>
    </head>
     
    <body>
    <h1>Struts 2 + Hibernate integration example</h1>
     
    <h2>Add Customer</h2>
    <s:form action="addCustomerAction" >
      <s:textfield name="name" label="Name" value="" />
      <s:textarea name="address" label="Address" value="" cols="50" rows="5" />
      <s:submit />
    </s:form>
     
    <h2>All Customers</h2>
     
    <s:if test="customerList.size() > 0">
    <table border="1px" cellpadding="8px">
    	<tr>
    		<th>Customer Id</th>
    		<th>Name</th>
    		<th>Address</th>
    		<th>Created Date</th>
    	</tr>
    	<s:iterator value="customerList" status="userStatus">
    		<tr>
    			<td><s:property value="customerId" /></td>
    			<td><s:property value="name" /></td>
    			<td><s:property value="address" /></td>
    			<td><s:date name="createdDate" format="dd/MM/yyyy" /></td>
    		</tr>
    	</s:iterator>
    </table>
    </s:if>
    <br/>
    <br/>
     
    </body>
    </html>

and finally the struts.xml..

    <struts>
      <constant name="struts.devMode" value="true" />
     
      <package name="default" namespace="/" extends="struts-default">
     
        <action name="addCustomerAction" 
    	class="com.mkyong.customer.action.CustomerAction" method="addCustomer" >
           <result name="success">pages/customer.jsp</result>
        </action>
     
        <action name="listCustomerAction" 
    	class="com.mkyong.customer.action.CustomerAction" method="listCustomer" >
            <result name="success">pages/customer.jsp</result>
        </action>		
     
      </package>	
    </struts>





