AOP – Spring – Hibernate Sessions for background threads / jobs

Getting your persistence access right when working with background jobs in Spring can be tricky. Most people rely on the Open Session In View pattern using Filters or Interceptors that act on the regular app server threads and close and open sessions for each request.

This technique is not available when you need access to your persistence context from a Quartz Scheduled Job or a TimerTask. The purpose of this tutorials is to show you how you can use Spring AOP proxies to wire a hibernate interceptor that gives you access to the persistence context and it takes cares of closing and opening the sessions for you.

This tutorial is available for download with svn:

svn checkout http://raulrajatutorials.googlecode.com/svn/trunk/ raulrajatutorials-read-only

Comments in the code itself should be self-explanatory if you already have some java + spring experience

And now to the point.

ApplicationContext.xml

<?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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
 
 
    <!-- The datasource -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
			<property name="driverClass" value="org.postgresql.Driver" />
			<property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/tutorials?autoReconnect=true" />
			<property name="user" value="tutorials" />
			<property name="password" value="tutorials" />
	</bean>
 
    <!-- The hibernate session factory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="configLocations">
            <list>
                <value>WEB-INF/conf/hibernate.cfg.xml</value>
            </list>
        </property>
        <property name="configurationClass">
            <value>org.hibernate.cfg.AnnotationConfiguration</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
        <property name="dataSource">
            <ref bean="dataSource"/>
        </property>
    </bean>
 
    <!-- The Hibernate interceptor, which takes care of opening and closing hibernate session around method calls. -->
    <bean id="hibernateInterceptor" class="org.springframework.orm.hibernate3.HibernateInterceptor">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
    </bean>
 
    <!-- The quartz scheduler in charge of running background jobs -->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" destroy-method="destroy">
        <property name="triggers">
            <list>
               <ref bean="testBackgroundJobTrigger"/>
            </list>
        </property>
        <property name="quartzProperties">
            <props>
                <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
                <prop key="org.quartz.threadPool.threadCount">20</prop>
                <prop key="org.quartz.threadPool.threadPriority">2</prop>
            </props>
        </property>
    </bean>
 
    <!-- A trigger bean with config info on how to run the background job -->
    <bean id="testBackgroundJobTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
        <property name="jobDetail" ref="testBackgroundJobDetail"/>
        <property name="startDelay" value="10000"/>
        <property name="repeatInterval" value="10000" />
    </bean>
 
    <!-- The actual background job impl that we're going to run -->
    <bean id="testBackgroundJob" class="com.raulraja.util.jobs.impl.TestBackgroundJobImpl" autowire="autodetect" />
 
    <!-- A proxy with the hibernate interceptor wired in so it can access the persistent context -->
    <bean id="testBackgroundJobProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target">
            <ref bean="testBackgroundJob"/>
        </property>
        <property name="proxyInterfaces">
            <value>java.lang.Runnable</value>
        </property>
        <property name="interceptorNames">
            <value>hibernateInterceptor</value>
        </property>
    </bean>
 
    <!-- Detail info about the job -->
    <bean id="testBackgroundJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="testBackgroundJobProxy"/>
        <property name="targetMethod" value="run"/>
        <property name="concurrent" value="false"/>
    </bean>
 
</beans>

TestBackgroundJobImpl.java

package com.raulraja.util.jobs.impl;
 
import org.apache.log4j.Logger;
 
/**
 * Test job that runs on the background
 */
public class TestBackgroundJobImpl implements Runnable {
 
	private final static Logger logger = Logger.getLogger(TestBackgroundJobImpl.class);
 
	/**
	 * Do something in the background
	 */
	public void run() {
		logger.debug("doing something in the background");
	}
}

Output


06/13 15:05:00 DEBUG org.springframework.orm.hibernate3.SessionFactoryUtils - Opening Hibernate Session
06/13 15:05:00 DEBUG com.raulraja.util.jobs.impl.TestBackgroundJobImpl - doing something in the background
06/13 15:05:00 DEBUG org.springframework.orm.hibernate3.HibernateInterceptor - Eagerly flushing Hibernate session
06/13 15:05:00 DEBUG org.springframework.orm.hibernate3.SessionFactoryUtils - Closing Hibernate Session

Discuss
17 Comments
  1. Thanks mate,

    This was totally what I was looking for – you’ve saved me a lot of time as I don’t have to work this one out myself. I’m using Hibernate, Spring, Struts and Jasper so I needed to work out how to get a scheduled job to call DAO’s where I could re-cycle the existing OSIV – rather then re-write anything..

    Super..keep up the good work!

  2. Jani says:

    Hi rual,

    Thank you for the information here.

    I am having a similar situation where we have to run several quartz shceduled jobs /triggers to update information.

    I tried the proxy apporoach you mentioned but still I can’t get it worked.

    The trigger I am trying to use is:

    java.lang.Runnable

    hibernateInterceptorAU
    hibernateInterceptorHK

    Can you please help to solve this?

    Thanks in advance,
    Jani

  3. Raul Raja says:

    Hi Jani, try posting your comment again running your code through http://www.elliotswan.com/postable/ first, thanks.

  4. Mira says:

    Hi
    I would like to know if we can use
    1. one hibernate session per multiple quartz jobs.
    2. can one have embedded jobs so that the top job has one hibernate session and that hibernate session can be used by the inner job.

    The idea is i have to cache some objects that are huge in number .so would like to cache it at frequency of one per day and the inner jobs run every two minute and would be using the cached job and will be hitting the database for other accessory work.
    thanks

  5. Raul Raja says:

    Hi,

    In my opinion you could use ehcache or some other cache system for that. I’m not sure what using the same session will help you with.

  6. Jose says:

    Raul,

    Thanks for this awesome approach, just one question, if I’m using JPA how could this be possible ? Is it way too different from this ?

    Thanks!

  7. Raul Raja says:

    Hi Jose,

    In the case of JPA it really depends on what impl of JPA you’re using. If you’re using JPA through Hibernate I’m guessing is the same.
    Spring comes with a hibernate interceptor built in but the implementation is trivial.
    Basically what you want to do for JPA or any other framework that supports transactions is to create an implementation of a org.aopalliance.intercept.MethodInterceptor …

    public class YourTransactionInterceptor implements MethodInterceptor {

    public Object invoke(MethodInvocation invocation) throws Throwable {
    Object result = null;
    Transaction tx = startYourTransaction();
    try {
    result = invocation.proceed(); //this calls the method adviced
    tx.success()
    } catch(Throwable e) {
    tx.rollback();
    } finally {
    tx.finish()
    }
    return result;
    }

    }

    then when you want to provide advice to any method you can wire it with spring with a ProxyFactoryBean like in the example or if you rather do it on java you can do it programmatically like this…

    ProxyFactory factory = new ProxyFactory(yourObject);
    Advised advised = (Advised) factory.getProxy();
    advised.addAdvice(yourTransactionInterceptor);
    YourObject aVersionOfYourObjectAdvised = (YourObject) advised;
    aVersionOfYourObjectAdvised.doSomethingInATransaction();

    As you can see the technique is much like the Open View in Session filter where you can just get transactions and sessions in the context they’re needed, since you don’t have a thread bound to the web request in this case you can’t use a servlet filter but you can always use a interceptor.

  8. Thanks for your post!

    I’ve updated your source code to work with JPA 2.0: read at http://chicchiricco.blogspot.com/2011/07/aop-spring-jpa-for-background-threads.html.

  9. Lucas says:

    I am aware you posted this last year and I’m not as proficient with persistence as I would like to be.
    On question I have is:
    If you want to retrieve all the the rows from table A. How would you do that in TestBackgroundJobImpl.run()?

    I really don’t know which way to go to get the session and to create a Criteria object.
    Thanks in advance,
    Lucas

  10. Lucas says:

    Hi Raul,
    I found the answer to my own question, I should use autowiring which is what I was using before in my app:
    @Autowired
    private ObjectService object_service;
    public void run() {
    List objects = object_service.findAllObject();
    }

    Thank you for this useful post, seriously, I spent a lot of time trying to figure this out.
    I’m sorry for clustering your page with questions.
    Thanks once more,
    Lucas

  11. Raul Raja says:

    Lucas, glad you found the answer and you found the post useful!

  12. Raul Raja says:

    Lucas aslo if you’re using JPA you should be able to just inject the persistence context with:

    @PersistenceContext
    private EntityManager entityManager;

    entityManager.createQuery(…).setParameter(“…”, …).getResultList();

  13. Nicolás says:

    Hola Raúl,

    En mi caso estoy tratando de utilizar un pool de hilos para ejecutar tareas. java.util.concurrent). En mi caso quiero que se vayan resolviendo a medida que van llegando las tareas, no cada cierto período de tiempo.

    Como puedo proveer mis workers su correspondiente sesión de Hibernate?

    un pseudo-código de lo que quiero hacer sería el siguiente:

    ExecutorService servicePool = Executors.newFixedThreadPool(10);

    public void processJob(CustomJob job) {

    servicePool.execute(new RequestJob(job.getId());

    }

    donde Request implementa la interfaz Runnable.

    Desde ya, muchas gracias!
    saludos

  14. Raul Raja says:

    Nicolás, la parte importante del tutorial es que el contenedor de Spring es capaz de crear un proxy para tus servicios el cual abre y cierra el contexto de persistencia alreadedor de invocaciones en los metodos. En tu caso puedes obetner un proxy de “RequestJob” programaticamente de forma que la invocación del metodo a tu elección ya estaría dentro de las sessión de hibernate por ejemplo:

    <bean id="testBackgroundJobProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target">
    <ref bean="referenciaATuJobRequestQueImplementaRunnable"/>
    </property>
    <property name="proxyInterfaces">
    <value>java.lang.Runnable</value>
    </property>
    <property name="interceptorNames">
    <value>hibernateInterceptor</value>
    </property>
    </bean>

    y lo obtienes:

    applicationContext.getBean(“testBackgroundJobProxy”);

    Buena suerte y ya me cuentas

  15. Alberto says:

    Do you know the difference between HibernateInterceptor and TransactionInterceptor? I am trying to take over some code that is using TransactionInterceptor with the same purpose.

  16. Raul Raja says:

    @Alberto, AFAIK the TransactionInterceptor is used to declaratively configure pointcuts that will be surrounded by a transaction. For example methods of a given service. As far as the HibernateInterceptor in this post is mostly to open and close the session automatically in background threads. You should be able to use the TransactionInterceptor to provide a transaction when you think is necessary or @Transactional if you’d rather configure it with annotations.

  17. Alberto says:

    Thanks a lot!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">