JSR 352 如何将对象 (java.lang.Object) 存储为作业 属性?

JSR 352 How to store an object (java.lang.Object) as a job property?

JSR352 1.0 Final §9.3 批处理属性中,批处理属性定义为类型 java.lang.String:

Batch applications need a way to receive parameters when a job is initiated for execution. Properties can be defined by batch programming model artifacts, then have values passed to them when a job is initiated. Batch properties are string values.

这是一个例子:

Properties jobProps = new Properties();
jobProps.setProperty("props1", "value1");
jobProps.setProperty("props2", "value2");

// start
jobOperator.start("myjob", jobProps);

但是,我需要使用其他对象来完成这项工作。这个通用 "property" 可以是任何对象类型,因此 java.lang.Object。所以我正在寻找满足以下要求的解决方案:

有人可以帮忙吗?

这是我为您的用例想到的想法(即使它看起来确实像是一种解决方法)。

您可以通过注入一个或多个作业参数作为初始步骤的批处理属性,然后将初始步骤的持久用户数据与步骤一起使用,从而在作业实例的生命周期内(即跨重启)填充持久对象配置 allow-start-if-complete="true" 以确保该步骤始终运行。


详细:

JobOperator接口只允许您以单个[的形式将作业参数传递给批处理应用程序=51=] 对象。

所以是的,如果通过使用某些应用程序或其他上下文(如 CDI 会提供)来解决此限制不是一个好的选择,那么您必须执行类似序列化 Serializable 的操作(或编组 JAXB 对象)并将其设置为作业参数。

所以想当然地认为您要序列化一个名为 serializedObj 的 属性,为了定义一个持久且不可变的作业级对象,该作业看起来像什么?

从 "setup" 这样的步骤开始:

<step id="setup" next="step1" allow-start-if-complete="true">
    <batchlet ref="SetupBatchlet">
        <properties>
            <property name="serializedObj" value="#{jobParameters['serializedObj']}" />
        </properties>  

实施:

public class SetupBatchlet implements Batchlet, BonusPayoutConstants {

    @Inject
    @BatchProperty(name = "serializedObj")
    private String serializedObjStr;

    @Inject
    private JobContext jobCtx;

    @Inject
    private StepContext stepCtx;

    @Override
    public String process() throws Exception {

        // 1. See if step persistent user data already exists
        MyObject myObj = (MyObject) stepCtx.getPersistentUserData();

        // 2. If not, deserialize
        if (myObj == null) {
            myObj = ...  // deserialize "serializedObjStr"
            // 2a. Persist user data
            stepCtx.setPersistentUserData(myObj);
        }

        // 3. set for use by later steps
        jobCtx.setTransientUserData(myObj);

现在第 1 步和后面的步骤可以执行:

MyObject myObj = (MyObject) jobCtx.getTransientUserData();

所以这个 MyObject 实例是持久且不可变的。 allow-start-if-complete="true" 配置确保 "setup" 步骤始终运行,并且始终填充 JobContext。

如果您需要聚合多个对象,这可以扩展,尽管它在某个时候可能会变得丑陋;同样的想法仍然可以应用。