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

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • LinkedIn
  • MySpace
  • RSS
  • TwitThis
  • email
  • FriendFeed
  • PDF
  • Slashdot

This post is tagged , ,

don't '

7 Responses

  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.

Leave a Reply

Comments may be held for moderation, please do not repost. I reserve the right to remove any inappropriate or off-topic comments. If you plan on sharing helpful code, please pass it through Postable first. Want other to know who you are? Register a Gravatar.





Sponsored Links

Categories

Pages

juice141
insurance158
gardens47
jewelers93
bestyoucanfind.info
heart146
james29
lyrics167
industries92
google142
lafayette9
kitchen229
lyrics120
jesus90
italian248
lyrics1
afreeocx.com
guide24
manhattan166
green201
information113
frank168
lyrics160
lyrics190
family142
kofflerboats.com
hitachi214
festival182
forest102
jamaica25
hotel86
executive74
guide23
flavor28
grant172
hockey221
free-microsofts.com
lyrics239
thesagamore.com
failed120
hockey220
healthbenefitsdepot.com
generic67
exchange72
fever194
island235
games21
italy249
manual188
management155
excellpressurewashers.com
library131
gibson97
grill212
marble210
flights35
hotel150
manitoba168
manual186
found137
finance231
house216
install128
institute139
lyric61
garden44
katie169
guitar51
festival181
hotels171
house189
franchise158
columbiatn.com
insurance150
guitar58
illinois22
louisville24
little204
festival189
height163
lyric67
guitar48
lyrics152
lyric48
lacrosse6
hotel154
georgia80
marine233
fitness19
cam.com
hospital62
hunter243
magazine103
floyd73
living210
sex-teen.org
lyrics46
honda22
honey36
mmgins.com
hotel142
ithaca3
lyrics202
lyrics142
management154
lyrics50
hunting247
harold105
creeksidepreserve.com
logic235
forum124
letter111
industrial90
lyrics31
gainesville242
hotel138
island224
heaters152
lyrics171
lyric69
marysvilleohio.org
gauge53
laboratories3
estate2
fields205
infant100
hairstyles77
indian72
james35
ireland214
maine125
houston231
malta148
jones128
fireplace241
honey36
rustyiron.com
finder236
germany90
jessica88
magnum119
fruit195
lyrics235
inurl204
guild36
lyrics37
kennel188
groups248
handbags91
freedom177
jeremy71
lyric81
furnace215
falls129
installing131
manufacturing203
lauderdale58
hotels176
major128
estate25
kenwood198
guitar47
hyderabad7
lyrics129
latex53
fabric103
lonsberry.com
lyrics147
maine123
sunyacc.edu
james27
veostingray.com
landing17
gallery12
lyrics231
madden90
furniture217
lyrics179
fountain146
little197
indian70
lounge27
lyrics121
keygen206
kevin201
import41
foster135
happy95
history199
jones124
kitten231
furniture236
manor170
language22
festival186
flash24
guitar43
lyrics44
homes8
hawaii119
hotel108
madden90
knight236
goneglobal35.com
florist65
myispfinder.org
lyric81
estate12
grand166
estate40
lyrics126
guitars67
fiber195
jumper148
limited160
hamilton85
female171
hospital67
instant132
estate6
glasses123
legal90
level116
pdc.org
estate18
india67
gallery13
kingdom217
florida59
katrina172
lyric76
linux183
football89
ingredients119
gymnastics73
houston229
humidifier241
naral.org
flying75
jewelry102
marine235
internet191
hotel133
hospital54
finder236
katrina172
listing193
lodge228
johnny110
mygibline.com
lyrics231
exhaust83
india54
little196
fuelmaker.com
lyrics163
harrison108
europe51
leather84
luggage33
gallery1
london242
lyrics67
magnum119
italy249
gallery3
lyrics9
london246
24fusion.info
hawaii118
lyric69
great186
thunderwear.com
market243
lyrics200
guide23
james27
linux179
houston222
example60
louisiana21
living211
maison127
californiaduihelp.com
fisher8
lyrics42
horses52
horse46
genesis68
indianapolis82
headphones123
lyrics201
forum123
local219
jelly60
malaysia144
fender177
lyric65
factory116
nomino.ca
greensboro206
express93
humidifier241
lights156
exercise76
girls104
jewish103
honda17
pulaskicountyassessor.net
lyric78
lyric75
harley103
group234
houses217
hockey219
lynch39
machine76
honda31
island229
gymnastics73
harvard114
katie168
infant100
lyrics207
language33
financialhack.com
login238
garcia35
manufacturer202
banana1015.com