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
。所以我正在寻找满足以下要求的解决方案:
- 存储的属性应该是不可变的,这意味着一旦传递给批处理运行时,它就不会再次更改。
- 属性 应该在作业停止时保留,并且可以在作业重新启动时重新使用。 (可序列化?)
- 变通解决方案不应依赖于任何实现,例如来自 JBoss 的 JBeret。因为我正在开发一个框架,它让用户选择自己的 JSR 352 实现。
有人可以帮忙吗?
这是我为您的用例想到的想法(即使它看起来确实像是一种解决方法)。
您可以通过注入一个或多个作业参数作为初始步骤的批处理属性,然后将初始步骤的持久用户数据与步骤一起使用,从而在作业实例的生命周期内(即跨重启)填充持久对象配置 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。
如果您需要聚合多个对象,这可以扩展,尽管它在某个时候可能会变得丑陋;同样的想法仍然可以应用。
在 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
。所以我正在寻找满足以下要求的解决方案:
- 存储的属性应该是不可变的,这意味着一旦传递给批处理运行时,它就不会再次更改。
- 属性 应该在作业停止时保留,并且可以在作业重新启动时重新使用。 (可序列化?)
- 变通解决方案不应依赖于任何实现,例如来自 JBoss 的 JBeret。因为我正在开发一个框架,它让用户选择自己的 JSR 352 实现。
有人可以帮忙吗?
这是我为您的用例想到的想法(即使它看起来确实像是一种解决方法)。
您可以通过注入一个或多个作业参数作为初始步骤的批处理属性,然后将初始步骤的持久用户数据与步骤一起使用,从而在作业实例的生命周期内(即跨重启)填充持久对象配置 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。
如果您需要聚合多个对象,这可以扩展,尽管它在某个时候可能会变得丑陋;同样的想法仍然可以应用。