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

时间:2016-09-16 16:15:35

标签: java-ee jsr352

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

  

批处理应用程序需要一种在启动作业执行时接收参数的方法。可以通过批处理编程模型工件来定义属性,然后在启动作业时将值传递给它们。 批次属性是字符串值。

这是一个例子:

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

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

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

  • 存储的属性应该是不可变的,这意味着一旦传递给批处理运行时,它就不会再被更改。
  • 当作业停止时,属性应该保留,并且可以在作业重新启动时重复使用。 (序列化?)
  • 解决方案解决方案不应依赖于任何实现,例如来自JBoss的JBeret。因为我正在开发一个框架,让用户可以选择自己的JSR 352实现。

有人可以帮忙吗?

1 个答案:

答案 0 :(得分:3)

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

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

详细说明:

JobOperator 界面只允许您以单个 java.util.Properties 对象的形式将作业参数传递给批处理应用程序。

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

所以理所当然地认为你要序列化一个名为serializedObj的属性,那么为了定义一个持久且不可变的作业级对象,工作会是什么样的呢?

从这样的“设置”步骤开始:

<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);

现在step1和后面的步骤可以做到:

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

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

如果您需要聚合多个对象,虽然它可能在某个点上变得丑陋,但这可以扩展;仍然可以应用相同的想法。