Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transaction Issue with Spring Batch JobRepository in Unit Test

Could anybody help me figure out the solution to the following exception, I guess I just don't quite understand the Transaction Propagation mechanism, which hinder me from understanding the true meaning of the exception message shown below, so please, help me understanding the whole thing, thank you so much indeed!

java.lang.IllegalStateException: Existing transaction detected in JobRepository. Please fix this and try again (e.g. remove @Transactional annotations from client).
at org.springframework.batch.core.repository.support.AbstractJobRepositoryFactoryBean$1.invoke(AbstractJobRepositoryFactoryBean.java:164)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy15.createJobExecution(Unknown Source)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:111)
at TestJob.testExcelParserTasklet(TestJob.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
at org.testng.internal.MethodInvocationHelper$1.runTestMethod(MethodInvocationHelper.java:169)
at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.run(AbstractTestNGSpringContextTests.java:158)

Here is the code resulting the above exception:

public class TestJob extends BaseTest {
@Test
public void testExcelParserTasklet() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, NoSuchJobException {
    Job job = jobRegistry.getJob("parseExcelJob");
    jobLauncher.run(job, new JobParameters());
    }
}

And here is the BaseTest:

@ContextConfiguration("classpath:application-context.xml")
public abstract class BaseTest extends AbstractTransactionalTestNGSpringContextTests
{
    @Autowired
    protected JobRegistry jobRegistry;

    @Autowired
    protected JobLauncher jobLauncher;
}
like image 818
user3184625 Avatar asked Jan 11 '14 09:01

user3184625


1 Answers

AbstractTransactionalTestNGSpringContextTests wraps all your test methods in a transaction. Spring batch job repository does not like to share its transaction manager with others. The logic is simple, if you share your job transaction manager with your step transaction manager upon step failure it will rollback both the step and the data written to the job repository. This means that you will not persist data for job restart. So the use of Transactional Unit tests is tricky.

Look at the section 4.3.1. Transaction Configuration for the JobRepository of the Spring Batch documentation.

We had this issue as well, so we avoid transactional tests until we will found a solution. The use of multiply transaction managers may work, but I haven’t tried it yet see How to configure mutliple transaction managers with Spring + DBUnit + JUnit

like image 82
Haim Raman Avatar answered Sep 26 '22 21:09

Haim Raman