Java批处理:未通过步骤传递jobContext transientUserData

Java批处理:未通过步骤传递jobContext transientUserData,java,jsr352,jberet,Java,Jsr352,Jberet,我正在使用JBeret实现jsr-352规范 简而言之,这是我的作业配置: <job id="expired-customer-cancellation" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://

我正在使用JBeret实现jsr-352规范

简而言之,这是我的作业配置:

<job id="expired-customer-cancellation" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/jobXML_1_0.xsd"
     version="1.0" jsl-name="job-parent" parent="job-parent">
    <step id="step1" next="step2">
        <chunk item-count="#{jobParameters['chunksize']}?:3">
            <reader ref="eccReader">
            </reader>
            <writer ref="eccWriter" />
        </chunk>
        <partition>
            <mapper ref="eccMapper">
                <properties>
                    <property name="threads" value="#{jobParameters['threads']}?:3"/>
                    <property name="records" value="#{jobParameters['records']}?:30"/>
                </properties>
            </mapper>
        </partition>
    </step>
    <step id="step2">
        <batchlet ref="eccMailBatchlet" />
    </step>
</job>

Itemwriter类执行如下操作:

@Named
public class EccWriter extends AbstractItemWriter {

    @Inject
    Logger logger;

    @Inject
    JobContext jobContext;

    @Override
    public void writeItems(List<Object> list) throws Exception {
        @SuppressWarnings("unchecked")
        ArrayList<String> processed = Optional.ofNullable(jobContext.getTransientUserData()).map(ArrayList.class::cast).orElse(new ArrayList<String>());
        list.stream().map(UserLogin.class::cast).forEach(input -> {

            if (someConditions) {

                processed.add(input.getUserId());

            }
        });

        jobContext.setTransientUserData(processed); // update job transient data with processed list
    }
}
@Named
公共类EccWriter扩展了AbstractItemWriter{
@注入
记录器;
@注入
工作环境工作环境;
@凌驾
public void writeItems(列表)引发异常{
@抑制警告(“未选中”)
ArrayList processed=Optional.ofNullable(jobContext.getTransientUserData()).map(ArrayList.class::cast).orElse(new ArrayList());
list.stream().map(UserLogin.class::cast).forEach(输入->{
如果(某些条件){
processed.add(input.getUserId());
}
});
jobContext.setTransientUserData(已处理);//使用已处理列表更新作业临时数据
}
}
现在,我希望在步骤2上调用jobContext.getTransientUserData()时获得更新的列表,而得到的只是一个null

此外,每个分区都有自己的jobContext.transientUserData,因此它在分区开始时总是以null值开始

我认为jobContext本身可能会因其名称而导致常见错误


什么是通过整个作业带来一些数据的自然方式?

这是当前API中的一个空白,我同意,“线程本地”行为可能会令人惊讶

您可以使用的一种技术是使用step持久化用户数据

例如,从步骤1开始:

StepExecution.setPersistentUserData(已处理)

然后从步骤2开始:

@Inject 
JobContext ctx;

List<StepExecution> stepExecs = BatchRuntime.getJobOperator().getStepExecutions(ctx.getInstanceId());

// ... not shown here, but sort through stepExecs and find the one from step1.
StepExecution step2Exec = ... ;  

Serializable userData = step2Exec.getPersistentUserData()
@Inject
JobContext-ctx;
List stepExecs=BatchRuntime.getJobOperator().getStepExecutions(ctx.getInstanceId());
// ... 此处未显示,但对StepExec进行排序,并从step1中找到一个。
StepExecution step2Exec=;
Serializable userData=step2Exec.getPersistentUserData()

这是之前提到的一个需要改进的地方,在雅加达批次(规范的新家)的未来增强中应该考虑到这一点。

感谢您的提示。另一种可能的方法是通过生产者使用作业范围对象。另请看好主意,我的答案至少对任何实现都是好的,对于特定的impl可能有更好的方法。