• Home
  • About
Blue Orange Green Pink Purple

Using Spring to manage Hibernate sessions in Struts2 (and other web frameworks)

Posted in code. on Wednesday, January 13th, 2010 by Chris Hulbert
Jan 13

It is actually quite easy to get Spring to manage your Hibernate sessions and inject them into your web handlers. There's just some config files that need some hard-to-find values. Here i'll show you the basics, from the perspective of a Struts2 application, although it'll be mostly the same for whichever web framework you use.

Your WebContent\WEB-INF\applicationContext.xml file will look like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

  <!-- The singleton hibernate session factory -->
  <bean id="sessionFactory" scope="singleton"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="configLocation" value="classpath:hibernate.cfg.xml" />
  </bean>

  <!-- Spring's hibernate transaction manager, in charge of making hibernate sessions/txns -->
  <bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
  </bean>

  <!-- So classes/functions with @Transactional get a hibernate txn -->
  <tx:annotation-driven />

  <!-- The singleton business services class, to be given to the actions -->
  <bean id="services" class="services.Services" scope="singleton">
    <property name="sessionFactory" ref="sessionFactory" />
  </bean>

</beans>

You'll then want a singleton business services class (or more than one) that looks like this. The idea is that spring passes it the session factory, and the @Transactional annotation tells spring to create hibernate sessions and transactions accordingly, so that the sessionFactory.getCurrentSession() always returns the appropriate session. In my case, this is named src\services\Services.java:

package services;
import org.springframework.transaction.annotation.Transactional;
import org.hibernate.SessionFactory;
import org.hibernate.Session;
import data.Event; // An example of a hibernate data class

// This class is the business services tier in the application.
// @Transactional is needed so that a Hibernate transaction is set up,
//  otherwise updates won't have an affect
@Transactional
public class Services {
  // So Spring can inject the session factory
  protected SessionFactory sessionFactory;
  public void setSessionFactory(SessionFactory value) {
    sessionFactory = value;
  }

  // Shortcut for sessionFactory.getCurrentSession()
  protected Session sess() {
    return sessionFactory.getCurrentSession();
  }

  // Example of a typical business service function
  public Event getEventById(long id) {
    return (Event) sess().load(Event.class, id);
  }
}

Your WebContent\WEB-INF\web.xml will need these lines in your <web-app> section:

  <!-- Spring -->
  <listener> <!-- Required for the struts2 spring plugin to work -->
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <filter> <!-- Get spring to keep the session open for the whole request, so hibernate's lazy loads work -->
    <filter-name>openSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>openSessionInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

Your src\hibernate.cfg.xml should look like this (in this case, i'm using jtds to access a sql server):

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <!-- Database connection settings -->
    <property name="connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
    <property name="connection.url">jdbc:jtds:sqlserver://DATABASE-SERVER-NAME/DATABASE-SCHEMA</property>
    <property name="connection.username">USERNAME</property>
    <property name="connection.password">PASSWORD</property>
    <property name="dialect">org.hibernate.dialect.SQLServerDialect</property>

    <!--
      Enable c3p0 connection pooling, because hibernate pooling is not
      prod-ready. Apparently connection.provider_class is needed in
      hibernate 3+
    -->
    <property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
    <property name="c3p0.max_size">100</property>
    <property name="c3p0.min_size">1</property>
    <property name="c3p0.idle_test_period">30</property>

    <!-- Echo all executed SQL to stdout for debugging -->
    <property name="show_sql">true</property>

    <!-- All the entity classes for hibernate to check for annotations here -->
    <mapping class="data.Whatever" />
  </session-factory>
</hibernate-configuration>

And in your Struts2 actions (or whatever is appropriate for your web framework of choice), you'll need a setter to receive the business services class:

package actions.base;

import services.Services;
import com.opensymphony.xwork2.ActionSupport;

public class SomeAction extends ActionSupport {
  // So that spring can inject the business singleton
  protected Services services;
  public void setServices(Services value) {
    services=value;
  }

  public String execute() {
    Event event = services.getEventById(1); // Just an example
    return "success";
  }
}

Also, if you're using Struts2, you'll need the struts2-spring-plugin-2.*.jar in your WebContent\WEB-INF\lib folder. Other frameworks will probably need something else done so that they use Spring to create and pass the business services to their actions/request handlers.

That should be it! I'll have to leave it up to you to figure out what JARs you need, but if you're a Java person, that's half the fun of it ;)

Any questions on the specifics here, feel free to fire away in the comments section!

1 Comment

  1. chaitanya on June 19th, 2010

    i am working on hibernate project . (c# windows) if user keeps syetem in hibernate, restart system, sleepmode, shutdown then these task times must be stored in database

    I used SystemEvents.PowerModeChanged to monitor from WinForm
    application and it work fine.

    I put that code in to Windows service application and it not seem to
    catch any power event.

    Help please? How can I monitor power change event from service
    application?

    Regards,
    chaitanya



Leave a Reply

Chris' Babble

  • About
    Hi, i'm Chris Hulbert, a software guy from Sydney Australia.
  • Categories
    • code
    • Portfolio
    • Uncategorized
  • Recent Articles
    • How to implement DES and Triple DES from scratch
    • How to use Cookies in Struts 2 with ServletRequest and ServletResponse
    • How to use sessions with Struts 2
    • Using Quartz Scheduler in a Java web app (servlet)
    • Javascript date picker that Doesn't Suck!(tm)
    • Using Oracle XE with Hibernate


  • Home
  • About

© Copyright Chris' Babble. All rights reserved.
Designed by FTL Wordpress Themes brought to you by Smashing Magazine

Back to Top