Skip to content

Missing note about not scoping Step beans with Job scope #3900

Closed
@kzander91

Description

@kzander91

Bug description
I have a Job that contains a Step that is annotated with @JobScope (to be able to inject job parameters).
Using JobOperator.stop() from another thread to stop that job fails with the following exception:

org.springframework.beans.factory.support.ScopeNotActiveException: Error creating bean with name 'scopedTarget.step': 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:383) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35) ~[spring-aop-5.3.6.jar:5.3.6]
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:195) ~[spring-aop-5.3.6.jar:5.3.6]
	at com.sun.proxy.$Proxy48.getName(Unknown Source) ~[na:na]
	at org.springframework.batch.core.job.SimpleJob.getStep(SimpleJob.java:109) ~[spring-batch-core-4.3.2.jar:4.3.2]
	at org.springframework.batch.core.launch.support.SimpleJobOperator.stop(SimpleJobOperator.java:402) ~[spring-batch-core-4.3.2.jar:4.3.2]
	at org.springframework.batch.core.launch.support.SimpleJobOperator$$FastClassBySpringCGLIB$$44ee6049.invoke(<generated>) ~[spring-batch-core-4.3.2.jar:4.3.2]
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.6.jar:5.3.6]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) ~[spring-aop-5.3.6.jar:5.3.6]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.6.jar:5.3.6]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.6.jar:5.3.6]
	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.6.jar:5.3.6]
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.6.jar:5.3.6]
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.6.jar:5.3.6]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.6.jar:5.3.6]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.6.jar:5.3.6]
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.3.6.jar:5.3.6]
	at org.springframework.batch.core.launch.support.SimpleJobOperator$$EnhancerBySpringCGLIB$$2759e0b7.stop(<generated>) ~[spring-batch-core-4.3.2.jar:4.3.2]
	at com.example.demo.DemoApplication.lambda$runner$0(DemoApplication.java:54) ~[classes/:na]
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:819) ~[spring-boot-2.4.5.jar:2.4.5]
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:803) ~[spring-boot-2.4.5.jar:2.4.5]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:346) ~[spring-boot-2.4.5.jar:2.4.5]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1340) ~[spring-boot-2.4.5.jar:2.4.5]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1329) ~[spring-boot-2.4.5.jar:2.4.5]
	at com.example.demo.DemoApplication.main(DemoApplication.java:91) ~[classes/:na]
Caused by: java.lang.IllegalStateException: No context holder available for job scope
	at org.springframework.batch.core.scope.JobScope.getContext(JobScope.java:159) ~[spring-batch-core-4.3.2.jar:4.3.2]
	at org.springframework.batch.core.scope.JobScope.get(JobScope.java:92) ~[spring-batch-core-4.3.2.jar:4.3.2]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:371) ~[spring-beans-5.3.6.jar:5.3.6]
	... 25 common frames omitted

Environment
Spring Batch: 4.3.2

Steps to reproduce

  1. Configure job with job-scoped steps.
  2. Run job asynchronously (to get hold of the pending JobExecution).
  3. Use JobOperator.stop() to stop that job.

Expected behavior
Stopping the job works, regardless of the scope of its steps.

Minimal Complete Reproducible example
Sample project:
demo.zip

The project contains a job-scoped step. A CommandLineRunner creates a JobLauncher that launches jobs asynchronously.
Then, the main thread waits two seconds before it calls JobOperator.stop().

  1. Unzip.
  2. Run ./mvnw spring-boot:run
  3. Two seconds after the job was started, JobOperator.stop() is called and fails with the exception above.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions