【发布时间】:2019-07-06 13:16:24
【问题描述】:
在我的 Web 应用程序中,我启动并管理了几十个 spring-batch 进程以进行长时间运行的操作。
在我看来,spring-batch 已经在 Web 应用程序上下文而不是作业上下文中构建了作业,从而导致了非信息性错误“No Scope registered for scope name 'step'”。
任何想法我错过了什么?
- Java 版本:1.8
- 春季版:5.1.3.RELEASE
- spring-batch 版本:4.1.1.RELEASE
- Tomcat 版本:8.0
自问题发布以来所做的更改/更新:
- 实现了作业注册表以封装作业,并更新了作业启动以使用作业注册表 - 无变化
- TARGET_CLASS 和 DEFAULT 代理模式都已尝试过并且功能相同 - 没有变化
- 根据 Mahmoud Ben Hassine 的回答在 StepScope bean 声明中添加了“
” - 没有变化
日志...
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 作业 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 { ... }
启动作业的代码...
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;
}
在 AbstractBeanFactory.doGetbean() 中,这是 spring 上下文的内容:
{request=org.springframework.web.context.request.RequestScope@3e707e1c, session=org.springframework.web.context.request.SessionScope@375463f}
更新:澄清回答
有许多代码问题导致了这种情况。
我要查找的类不在作业的任何上下文扫描路径中,但它在全局上下文扫描路径中。公共论坛的清理代码对任何响应者隐藏了这一点。
原始代码在整个应用程序中没有遵循代理模式的一致做法。没有理由不始终遵循一致的最佳做法。
作业注册表内部的错误使用导致了普遍的“怪异”。
至于原始问题中的“为什么”,答案是 Spring 在每个上下文的上下文扫描时评估范围。如果 bean 没有加载作业上下文(比如因为 job.xml 文件中缺少所需的类路径之一),那么在延迟加载时,Spring 会尝试加载 bean,并在父类路径中找到一个,这恰好是由网络配置扫描的那个。 bean 被声明为“Step”。 webconfig 当然没有 step 范围。
错误消息是正确的(英文:Yo dude,这个 bean 被声明为 step 范围,但在上下文中没有一个),并且具有误导性(我可以在作业中看到有一个 step 范围,它正在执行step 范围,其他 bean 都在 step 范围内运行,WTH ???!!!!!)。
我希望看到从 Spring 返回的更智能的错误消息。一次追踪完全准确但隐藏问题真正根源的错误消息很容易浪费数天时间。
【问题讨论】:
标签: java spring spring-batch