Skip to content

Conditional (Java configured) steps cannot be scoped [BATCH-2747] #857

Closed
@spring-projects-issues

Description

@spring-projects-issues

Mattias Jiderhamn opened BATCH-2747 and commented

Configuring conditional steps using Java config (XML untested) fails if any of the steps is scoped using Job scope or Step scope.

To reproduce, use the example at https://docs.spring.io/spring-batch/4.0.x/reference/html/step.html#controllingStepFlow, i.e.

@Bean
public Job job() {
        return this.jobBuilderFactory.get("job")
                                .start(stepA())
                                .on("*").to(stepB())
                                .from(stepA()).on("FAILED").to(stepC())
                                .end()
                                .build();
}

and then add @JobScope or @StepScope on stepA(), stepB() or stepC().

The underlying reason is that to configure a flow step, the framework wants to get the steps name using getName(), at which point the bean is resolved and the scope inferred.

Stack trace (4.0.1)

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myJob' defined in se.jiderhamn.ScopeTestConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.core.Job]: Factory method 'parseCallLogJob' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.stepA': Scope 'job' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for job scope
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:583)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1249)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1098)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:756)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128)
	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:109)
	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:246)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:117)
	... 24 more
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.core.Job]: Factory method 'parseCallLogJob' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.stepA': Scope 'job' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for job scope
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:186)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:575)
	... 41 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.stepA': Scope 'job' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for job scope
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:357)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
	at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:193)
	at com.sun.proxy.$Proxy32.getName(Unknown Source)
	at org.springframework.batch.core.job.builder.FlowBuilder.createState(FlowBuilder.java:282)
	at org.springframework.batch.core.job.builder.FlowBuilder.doStart(FlowBuilder.java:265)
	at org.springframework.batch.core.job.builder.FlowBuilder.start(FlowBuilder.java:122)
	at org.springframework.batch.core.job.builder.JobFlowBuilder.<init>(JobFlowBuilder.java:39)
	at org.springframework.batch.core.job.builder.SimpleJobBuilder.on(SimpleJobBuilder.java:91)
	at se.jiderhamn.ScopeTestConfiguration.parseCallLogJob(ScopeTestConfiguration.java:36)
	at se.jiderhamn.ScopeTestConfiguration$$EnhancerBySpringCGLIB$$240ba886.CGLIB$parseCallLogJob$3(<generated>)
	at se.jiderhamn.ScopeTestConfiguration$$EnhancerBySpringCGLIB$$240ba886$$FastClassBySpringCGLIB$$faf3ccf4.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:361)
	at se.jiderhamn.ScopeTestConfiguration$$EnhancerBySpringCGLIB$$240ba886.parseCallLogJob(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:155)
	... 42 more
Caused by: java.lang.IllegalStateException: No context holder available for job scope
	at org.springframework.batch.core.scope.JobScope.getContext(JobScope.java:159)
	at org.springframework.batch.core.scope.JobScope.get(JobScope.java:92)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:345)
	... 62 more

Affects: 4.0.1, 4.1.0.M2

Reference URL: https://stackoverflow.com/questions/55571210/

2 votes, 4 watchers

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions