Inside my web application, I launch and manage several dozen spring-batch processes for long running operations.
It looks to me like spring-batch has built the job in the web application context instead of the job context, resulting in the non-informative error "No Scope registered for scope name 'step'" .
Any ideas what I am missing?
Changes/updates made since the question was posted:
Log ...
taskExecutor-1 2019-02-12 13:31:32,836 ERROR o.s.b.c.s.AbstractStep - Encountered an error executing step step0002-init-prepareGraphDatastore in job hierarchy-analyser
java.lang.IllegalStateException: No Scope registered for scope name 'step'
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:350) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35) ~[spring-aop-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:672) ~[spring-aop-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at com.xxxx.MyExampleReader$$EnhancerBySpringCGLIB$$b0c58048.beforeStep(<generated>) ~[relationship-analyzer-tool-BASELINE.jar:na]
at org.springframework.batch.core.listener.CompositeStepExecutionListener.beforeStep(CompositeStepExecutionListener.java:77) ~[spring-batch-core-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:199) ~[spring-batch-core-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148) [spring-batch-core-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:68) [spring-batch-core-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:67) [spring-batch-core-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:169) [spring-batch-core-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144) [spring-batch-core-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:136) [spring-batch-core-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:313) [spring-batch-core-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:144) [spring-batch-core-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_162]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_162]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_162]
Spring-batch job XML ...
<?xml version="1.0" encoding="UTF-8"?>
<beans default-lazy-init="false"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:batch="http://www.springframework.org/schema/batch"
xsi:schemaLocation="
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
<description>Hierarchy Analyzer</description>
<context:component-scan
base-package="com.xxxx.*" />
<bean class="org.springframework.batch.core.scope.JobScope" />
<bean class="org.springframework.batch.core.scope.StepScope" />
<batch:job id="hierarchy-analyser">
<batch:listeners>
<batch:listener
ref="someJobListeners" />
</batch:listeners>
<batch:step id="step0002-init-long-running-process"
allow-start-if-complete="true">
<batch:tasklet
transaction-manager="jtaTransactionManager" start-limit="100">
<batch:chunk reader="myExampleReader"
writer="myExampleWriter" commit-interval="1" />
</batch:tasklet>
<batch:fail on="FAILED" />
<batch:next on="*"
to="step0002-1-more-stuff" />
<batch:listeners>
<batch:listener ref="myExampleReader" />
<batch:listener ref="myExampleWriter" />
</batch:listeners>
</batch:step>
</batch:job>
</beans>
MyExampleReader ...
@Component
@Scope(value = "step", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyExampleReader
implements ItemReader<TableMetadata>,
StepExecutionListener { ... }
Code that launches job ...
private ResultWrapper<Job> setupJobById(Resource r) throws Exception {
ResultWrapper<Job> result = new ResultWrapper<Job>();
try {
Resource[] res = new Resource[] { r };
ClasspathXmlApplicationContextsFactoryBean b = new ClasspathXmlApplicationContextsFactoryBean();
b.setApplicationContext(applicationContext);
b.setResources(res);
ApplicationContextJobFactory factory = new ApplicationContextJobFactory(
r.getFilename().substring(0, r.getFilename().lastIndexOf('.')), b.getObject()[0]);
result.succeed(factory.createJob());
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
result.fail(null, ex.getMessage(), ex);
}
return result;
}
Inside AbstractBeanFactory.doGetbean(), this is the contents of the spring context:
{request=org.springframework.web.context.request.RequestScope@3e707e1c, session=org.springframework.web.context.request.SessionScope@375463f}
Update: clarifications to answer
There were a number of code issues that contributed to this.
The class I was looking for was not in any of the context scan paths in the job, but it was in the global context scan path. Sanitizing code for public forums hid this from any responders.
The original code did not follow consistent practice for proxy modes throughout the application. There was no reason to not follow consistent best practices throughout.
Incorrect use of the job registry internals led to general "wierdness".
As to "why" in the original question, the answer is that Spring evaluates scope at context-scan time for each context. If the bean is not loaded with the job context (say because one of the classpaths required is missing from the job.xml file) then on lazy loading Spring attempts to load the bean, and finds one in the parent classpath, which happens to be the one scanned by the web config. The bean is declared "Step". The webconfig, of course has no step scope.
The error message is both correct (English: Yo dude, this bean is declared step scope, but there aint one in the context), and misleading (I can see in the job that there is a step scope, it's executing in the step scope, other beans are operating in the step scope, WTH ???!!!!!).
I would like to see more intelligent error messages returned from Spring. It is easy to lose days at a time chasing error messages that are completely accurate but hide the real source of the issue.
You are using proxyMode = ScopedProxyMode.TARGET_CLASS
on the scope of your reader, so you need to declare the step scope with:
<beans:bean class="org.springframework.batch.core.scope.StepScope">
<beans:property name="proxyTargetClass" value="true" />
</beans:bean>
EDIT: I know that there is an open issue about beans that don't get proxied when mixing Java config and XML config (See BATCH-2351 ), but I'm not sure you are hitting that issue here.
Here are a couple of things I would try:
<context:component-scan base-package="com.xxxx.*" />
and declare the MyExampleReader
using XML with scope="step"
after removing @Component
and @Scope(value = "step", proxyMode = ScopedProxyMode.TARGET_CLASS)
JobLauncher
and the Job
to launch. You can find an example here: https://docs.spring.io/spring-batch/4.1.x/reference/html/job.html#runningJobsFromWebContainerA similar question can be found here: Spring batch scope issue while using spring boot
Hope this helps.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.