0

Hy guys,

I want to run a spring batch job and then make some test on the data that result, but I need to use the hibernate lazy loading. So I need an opened transaction to keep the session alive.

But I get this exception : IllegalTransactionStateException : Pre-bound JDBC Connection found!

I could write methods to get directly the associated objects I want to test, but I don't want to write method only for test and to loose hibernate's advantages.

Is there a way to do this ? I've try to set the validateStateTransaction to false in the jobRepositoy but it doesn"t work (in fact it only work with a in memory meta data repository like MapJobRepository).

I'm searching for a couple of days but nothing that works.

Could you help me please ? Thanks

My code here :

<bean id="jobRepository"
    class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
    <property name="databaseType">
        <value>POSTGRES</value>
    </property>
    <property name="dataSource" ref="databasePool" />
    <property name="transactionManager" ref="transactionManager" />
    <property name="isolationLevelForCreate" value="ISOLATION_DEFAULT" />
    <property name="tablePrefix" value="#{ schema }.BATCH_" />
    <property name="validateTransactionState" value="false" />
</bean>

and

@Test
@Transactional
public void test() {

    /*
     * ===================RUN JOB======================
     */
    JobParameters jobParameters = new JobParametersBuilder();

    int returnCode = runJob("job_name", jobParameters);
    assertEquals("returnCode must be 0.", 0, returnCode );

    /*
     * ===============END JOB=============================
     */

    /*
     * ===============TEST ON DATA==========================
     */
    ObjectToTest obj = objectDao.findById("1");

    assertNotNull( obj.getSomeCollection().get(1));

    /*
     * =================END TEST==================
     */

}

Here is the exception :

org.springframework.transaction.IllegalTransactionStateException: Pre-bound JDBC Connection found! JpaTransactionManager does not support running within DataSourceTransactionManager if told to manage the DataSource itself. It is recommended to use a single JpaTransactionManager for all transactions on a single DataSource, no matter whether JPA or JDBC access.
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:359)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:438)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:261)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy113.getLastJobExecution(Unknown Source)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:98)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.start(CommandLineJobRunner.java:362)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.main(CommandLineJobRunner.java:590)
at fr.insee.harmonica.commun.batch.CommandLineJobRunnerTest.runJob(CommandLineJobRunnerTest.java:143)
at fr.insee.harmonica.commun.batch.CommandLineJobRunnerTest.execute(CommandLineJobRunnerTest.java:420)

I've try to put the test part in another method that would be anotated with @Transactional, but then I get a LazyInitializationException...

EDIT :

I use the org.springframework.orm.jpa.JpaTransactionManager implementation for transaction Manager.

Here is my spring configuration :

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="myEmf" />
</bean> 

<tx:annotation-driven transaction-manager="transactionManager"/>

I have searched the way to manually open transaction but I didn't find it yet

Philippe
  • 296
  • 2
  • 12

1 Answers1

0

Ok I found a solution (without any help finally).

To do this you have to open manually a transaction AFTER your job ends.

You can do something like that :

@Autowired
protected PlatformTransactionManager transactionManager;

@Test
public void test() {

/*
 * ===================RUN JOB======================
 */
JobParameters jobParameters = new JobParametersBuilder();

int returnCode = runJob("job_name", jobParameters);
assertEquals("returnCode must be 0.", 0, returnCode );

/*
 * ===============END JOB=============================
 */

/*
 * ===============TEST ON DATA==========================
 */
(new TransactionTemplate(transactionManager)).execute(new TransactionCallback() {
        @Override
        public Object doInTransaction(TransactionStatus status) {

          ObjectToTest obj = objectDao.findById("1");

          assertNotNull( obj.getSomeCollection().get(1));
 }
});

/*
 * =================END TEST==================
 */




}
Philippe
  • 296
  • 2
  • 12