首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用@JobScope中的步骤定义基于条件流java的Spring批处理

使用@JobScope中的步骤定义基于条件流java的Spring批处理
EN

Stack Overflow用户
提问于 2016-02-09 14:25:26
回答 2查看 13.9K关注 0票数 3

我在使用@JobScope中的步骤在包含条件流的Spring批处理中定义一个基于java的作业配置时遇到了问题,即在作业执行时将一个作业参数注入该步骤。

我的设置:

  • 弹簧批3.0.4
  • Spring批管理2.0.0.M1 (在运行时提供jobRepository、transactionManager、jobScope、stepScope bean)

假设我有一个包含两个步骤step1和step2的简单作业,那么在没有条件流的情况下定义和执行作业配置是有效的:

代码语言:javascript
运行
复制
@Configuration
public class SimpleJobConfiguration {

@Bean
@JobScope
Step1Tasklet step1Tasklet(@Value("#{jobParameters['condition']}") String condition) {
    Step1Tasklet tasklet = new Step1Tasklet(condition);
    return tasklet;
}

// reader, writer ommitted

@Bean
@JobScope
public Step step1(@Value("#{jobParameters['condition']}") String condition) {
    TaskletStep step = stepBuilderFactory().get(STEP_NAME_1)
            .tasklet(step1Tasklet(condition))
            .build();
    return step;
}

@Bean
@JobScope
public Step step2() {
    TaskletStep step = stepBuilderFactory().get(STEP_NAME_2)
            .<String, String>chunk(10)
            .reader(reader(null))
            .writer(writer())
            .allowStartIfComplete(true)
            .build();
    return step;
}

@Bean
public Job simpleJob() {
    Job job = jobBuilderFactory().get(JOB_NAME)
            .start(step1(null))
            .next(step2())
            .build();
    return job;
}
  • 在部署作业配置时,Spring正在初始化我的job ,没有任何例外,。它不初始化我的步骤-这是有意义的,因为它们在范围“作业”。
  • 当启动此作业配置的执行时,Spring将初始化这两个步骤,并按预期注入作业参数。
  • 该作业按预期执行,首先执行step1,然后执行step2。

现在,我想为我的工作添加一个简单的条件逻辑:

"IF“(步骤1.退出step2 == "OK")然后执行step2 OK作业”“

为此,我定义了一个决策bean (实现了JobExecutionDecider)并修改了我的职务定义:

代码语言:javascript
运行
复制
@Bean
public SimpleStepDecider decider() {
    SimpleStepDecider decider = new SimpleStepDecider(); 
    return decider;
}

@Bean
// DOES NOT WORK; NEEDS TO BE FIXED!
public Job simpleJob() {
    Job job = jobBuilderFactory().get(JOB_NAME)
            .start(step1(null))
            .next(decider())
            .on("OK")
            .to(step2())
            .end()
            .build();
    return job;
}

使用它,我在部署期间得到了以下异常(!)职务配置:

代码语言:javascript
运行
复制
14:28:07,299 ERROR batch.local-startStop-1 context.ContextLoader:331 - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'simpleJob' defined in com.foo.bar.SimpleJobConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.core.Job]: Factory method 'simpleJob' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.step1': 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:599)
...
        at org.springframework.batch.core.configuration.support.GenericApplicationContextFactory$ResourceXmlApplicationContext.<init>(GenericApplicationContextFactory.java:161)
...
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.core.Job]: Factory method 'simpleJob' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.step1': 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:189)
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
        ... 39 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.step1': 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:352)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
        at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:187)
        at com.sun.proxy.$Proxy33.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.next(SimpleJobBuilder.java:133)
        at com.foo.bar.SimpleJobConfiguration.simpleJob(SimpleJobConfiguration.java:145)
        ... 40 more
Caused by: java.lang.IllegalStateException: No context holder available for job scope
        at org.springframework.batch.core.scope.JobScope.getContext(JobScope.java:153)
        at org.springframework.batch.core.scope.JobScope.get(JobScope.java:92)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:337)
        ... 60 more

我试过:

  • 将步骤bean移动到“正常”范围
  • 使用步骤执行侦听器而不是判定器

但一点运气都没有..。

有趣的是,我能够使用基于xml的配置来定义相同的任务,并且它按预期的方式工作(decider使用作业参数‘code’的值作为退出状态代码;我测试了"OK“和"NOTOK”,它们都按预期工作):

代码语言:javascript
运行
复制
<bean id="reader" class="com.foo.bar.MyReader" scope="job">
</bean>

<bean id="writer" class="com.foo.bar.MyWriter" />

<bean id="decider" class="com.foo.bar.SimpleStepDecider" />

<bean id="step1Tasklet" class="com.foo.bar.Step1Tasklet" scope="job">
    <constructor-arg value="#{jobParameters['condition']}" />
</bean>

<batch:job id="simpleJob" restartable="true">
    <batch:step id="step1" next="decision" allow-start-if-complete="true">
        <batch:tasklet ref="step1Tasklet" />
    </batch:step>
    <batch:decision id="decision" decider="decider">
        <batch:end on="NOTOK" />
        <batch:next on="OK" to="step2"/>
        <batch:fail on="*"/>
    </batch:decision>
    <batch:step id="step2" allow-start-if-complete="true">
        <batch:tasklet allow-start-if-complete="true">
            <batch:chunk reader="reader" writer="writer" commit-interval="1000" />
        </batch:tasklet>
    </batch:step>
</batch:job>

有人能告诉我如何使我的java配置工作,即在作业执行期间实例化步骤bean吗?

EN

回答 2

Stack Overflow用户

发布于 2016-02-09 16:27:35

这可能是因为您正在遇到当前未解决的批处理-2229:无法在多线程或分区步骤中使用作业范围bean

这是在从分区和/或多线程步骤访问作业作用域bean时引发的:

带有分区步骤的春季批处理中的Access @JobScope bean

Spring批处理3.0中作业范围bean的多线程访问

票数 1
EN

Stack Overflow用户

发布于 2018-05-06 05:50:25

我认为问题是"step1(null)",尝试这样修改:

代码语言:javascript
运行
复制
public Job simpleJob(Step step1) {
Job job = jobBuilderFactory().get(JOB_NAME)
        .start(step1)
        .next(decider())
        .on("OK")
        .to(step2())
        .end()
        .build();
return job;}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35294496

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档