1

Using Spring Batch with an Oracle DB I occasionally run into a CannotSerializeTransactionException. However the commonly recommended fix to set the isolation-level-for-create to ISOLATION_REPEATABLE_READ as described in Spring Batch ORA-08177: can't serialize access for this transaction when running single job, SERIALIZED isolation level leaves Spring Batch unable to create the jobrepository.

What am I missing here?

The bean defintion for the jobrepository.

    @Bean
    public JobRepositoryFactoryBean jobRepository(
            final SessionFactory sessionFactory) {
        return new JobRepositoryFactoryBean() {
            {
                setTransactionManager(transactionManager(sessionFactory));
                setDataSource(dataSource);
                setIsolationLevelForCreate("ISOLATION_REPEATABLE_READ");
            }
        };
    }

The exception:

2014-11-06 08:47:31.714 ERROR   --- [           main] o.s.b.c.l.support.CommandLineJobRunner   : Job Terminated in error: Error creating bean with name 'jobBuilders' defined in class path resource [org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.batch.core.configuration.annotation.JobBuilderFactory org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration.jobBuilders() throws java.lang.Exception] threw exception; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobBuilders' defined in class path resource [org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.batch.core.configuration.annotation.JobBuilderFactory org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration.jobBuilders() throws java.lang.Exception] threw exception; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:597)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1094)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:989)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
    at org.springframework.batch.core.launch.support.CommandLineJobRunner.start(CommandLineJobRunner.java:288)
    at org.springframework.batch.core.launch.support.CommandLineJobRunner.main(CommandLineJobRunner.java:590)
    at nl.eci.matching.app.CommandLine.main(CommandLine.java:47)
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.batch.core.configuration.annotation.JobBuilderFactory org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration.jobBuilders() throws java.lang.Exception] threw exception; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:188)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:586)
    ... 15 common frames omitted
Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
    at org.springframework.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:721)
    at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:499)
    at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
    at org.springframework.cglib.proxy.Enhancer.create(Enhancer.java:285)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.enhanceFactoryBean(ConfigurationClassEnhancer.java:386)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:295)
    at org.springframework.batch.core.configuration.annotation.ModularBatchConfiguration$$EnhancerBySpringCGLIB$$ab2da3c9.jobRepository(<generated>)
    at org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration.jobBuilders(AbstractBatchConfiguration.java:61)
    at org.springframework.batch.core.configuration.annotation.ModularBatchConfiguration$$EnhancerBySpringCGLIB$$ab2da3c9.CGLIB$jobBuilders$8(<generated>)
    at org.springframework.batch.core.configuration.annotation.ModularBatchConfiguration$$EnhancerBySpringCGLIB$$ab2da3c9$$FastClassBySpringCGLIB$$f3de96e1.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312)
    at org.springframework.batch.core.configuration.annotation.ModularBatchConfiguration$$EnhancerBySpringCGLIB$$ab2da3c9.jobBuilders(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)
    ... 16 common frames omitted

For good measure, the original exception

2014-11-06 08:17:12.590 ERROR   --- [           main] o.s.b.c.l.support.CommandLineJobRunner   : Job Terminated in error: PreparedStatementCallback; SQL [INSERT into BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION) values (?, ?, ?, ?)]; ORA-08177: Kan toegang tot deze transactie niet rangschikken.
; nested exception is java.sql.SQLException: ORA-08177: Kan toegang tot deze transactie niet rangschikken.


org.springframework.dao.CannotSerializeTransactionException: PreparedStatementCallback; SQL [INSERT into BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION) values (?, ?, ?, ?)]; ORA-08177: Kan toegang tot deze transactie niet rangschikken.
; nested exception is java.sql.SQLException: ORA-08177: Kan toegang tot deze transactie niet rangschikken.

               at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:267)
               at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
               at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:660)
               at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:909)
               at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:970)
               at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:975)
               at org.springframework.batch.core.repository.dao.JdbcJobInstanceDao.createJobInstance(JdbcJobInstanceDao.java:115)
               at org.springframework.batch.core.repository.support.SimpleJobRepository.createJobExecution(SimpleJobRepository.java:135)
               at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
               at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
               at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
               at java.lang.reflect.Method.invoke(Method.java:601)
               at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
               at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
               at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
               at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
               at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
               at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
               at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
               at org.springframework.batch.core.repository.support.AbstractJobRepositoryFactoryBean$1.invoke(AbstractJobRepositoryFactoryBean.java:172)
               at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
               at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
               at $Proxy12.createJobExecution(Unknown Source)
               at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:125)
               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 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
               at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
               at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
               at java.lang.reflect.Method.invoke(Method.java:601)
               at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
               at java.lang.Thread.run(Thread.java:722)
Caused by: java.sql.SQLException: ORA-08177: Kan toegang tot deze transactie niet rangschikken.

               at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
               at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
               at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:951)
               at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:513)
               at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:227)
               at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
               at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:208)
               at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1046)
               at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1336)
               at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3613)
               at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3694)
               at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1354)
               at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:916)
               at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:909)
               at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:644)
               ... 29 common frames omitted
Community
  • 1
  • 1
M.P. Korstanje
  • 10,426
  • 3
  • 36
  • 58

1 Answers1

2

The issue is that you're returning a JobRepositoryFactoryBean but we're expecting a JobRepository. The jobRepository() methods that are there by default don't return the actual factory…they return the result. Because of that, the beanFactory is saying that you don't have a jobRepository available for the jobBuilder bean. To fix this, add the call to the FactoryBean#getObject() and change your return value like this:

@Bean
public JobRepository jobRepository(final SessionFactory sessionFactory) {

    JobRepositoryFactoryBean factory =  new JobRepositoryFactoryBean();
    factory.setTransactionManager(transactionManager(sessionFactory));
    factory.setDataSource(dataSource);
    factory.setIsolationLevelForCreate("ISOLATION_REPEATABLE_READ");

    return factory.getObject();
}
Michael Minella
  • 20,843
  • 4
  • 55
  • 67