从JSR 352中的分区步骤访问JobContext

时间:2014-03-10 16:45:54

标签: java batch-processing glassfish-4

我正在尝试在批处理之间传递一个对象,但是在尝试从分区步骤(batchlet)访问jobContext时遇到了问题。

根据JSR 352规范

  

9.4.1.1批处理上下文生命周期和范围:   批处理上下文具有线程关联性,仅对批处理可见   在该特定线程上执行的工件。注入批处理上下文   超出范围时,字段可能为null。每种上下文类型都有不同的   范围和生命周期如下:   1. JobContext   每个作业执行一个JobContext。它存在于一个人的生命中   工作。 并行的每个子线程都有一个独特的JobContext   执行(例如分区步骤)。   2. StepContext   每步执行一个StepContext。它存在于生命中   这一步。对于分区步骤,有一个StepContext   父步/线程;每个子线程都有一个独特的StepContext。

我的(失败)解决方案是使用JobContext.setTransientUserData,但由于分区步骤使用了不同的JobContext,我无法获取TransientUserData。

我有什么替代方法吗?使用PartitionMapper属性是不可能的,因为我需要将一个对象而不是一个字符串传递给每个分区。

要说清楚,我需要这样做:

  1. NormalBatchlet - >保存要在下一步中使用的对象。
  2. PartitionedBatchlet - >在上一步中获取保存的对象。此对象不是简单的String,因此使用PartitionMapper属性不是解决方案。
  3. 更新

    我现在使用带有HashMap的简单Singleton EJB在步骤之间存储对象,当作业完成时,我清除此映射以避免资源泄漏。

    这是一种解决方法,因为我真的只想使用javax.batch包而不依赖于EJB,所以我不是把它作为答案。

3 个答案:

答案 0 :(得分:7)

你可以尝试这样的东西,它应符合当前的规范编程模型。

使用NormalBatchlet中的持久性步骤数据存储第一步中的对象:

stepCtx.setPersistentUserData(mySerializableData);

通过查找上一步来检索分区中第一步的数据:

Long execId = jobCtx.getExecutionId();

List<StepExecution> stepExecs = jobOperator.getStepExecutions(execID);

MyPersistentUserData myData;

for (StepExecution step : stepExecs) {
    if (step.getStepName().equals("somePreviousStepX") {
        myData = (MyPersistentUserData)step.getPersistentUserData();
    }
}

//use myData

答案 1 :(得分:1)

没有一种规范定义的方法来共享主线程的JobContext和分区级JobContext之间的临时用户数据。这是一个可以理解的混淆点,但这确实是预期的设计。

答案 2 :(得分:0)

在规范中提到了访问Context - Injection的唯一方法。见第9.4.1段。

“9.4.1批量上下文

批处理上下文的批处理工件访问是使用标准的@Inject批注(javax.inject.Inject)进行注入。注入批处理上下文的字段不能是静态的,也不能是最终的。

E.g:

@Inject JobContext _jctxt;

@Inject StepContext _sctxt;

批处理运行时负责确保根据当前正在执行的作业或步骤注入正确的上下文对象。“