[英]Spring batch : Propagate exception encountered in partitioned step (Stop job execution)
[英]Spring Batch 3.0 : StepExecutionListener for a partitioned Step and cascading of execution context values to the partitioned job
给定一个使用分区的Spring 批处理作业:
<job id="reportingJob" xmlns="http://www.springframework.org/schema/batch">
<batch:listeners>
<batch:listener ref="reportingJobExecutionListenerr" />
</batch:listeners>
<batch:step id="reportingMasterStep">
<partition step="reportingSlaveStep"
partitioner="reportingPartitioner">
<batch:handler grid-size="10" task-executor="taskExecutor" />
</partition>
</batch:step>
</job>
而reportingSlaveStep
定义为:
<step id="reportingSlaveStep" xmlns="http://www.springframework.org/schema/batch">
<job ref="reportingSlaveJob" />
</step>
而reportingSlaveJob
定义为:
<job id="reportingSlaveJob" xmlns="http://www.springframework.org/schema/batch">
<batch:listeners>
<batch:listener ref="reportsOutputListener" />
</batch:listeners>
<batch:split id="reportsCreationSplit"
task-executor="taskExecutor">
<batch:flow>
<batch:step id="basicReportStep">
<tasklet throttle-limit="5" task-executor="taskExecutor">
<batch:chunk reader="basicReportReader"
writer="basicReportWriter" commit-interval="500" />
</tasklet>
</batch:step>
</batch:flow>
<batch:flow>
<batch:step id="advancedReportStep">
<tasklet throttle-limit="5" task-executor="taskExecutor">
<batch:chunk reader="advancedReportDataReader" writer="advancedReportWriter"
commit-interval="500" />
</tasklet>
</batch:step>
</batch:flow>
</batch:split>
</job>
我现在有两个问题:
reportsOutputListener
实例。 我可以通过将reportsOutputListener
设置为Step
范围的 bean 来实现这一点吗?reportingJob
创建的相同jobExecutionContext
,以便在reportingSlaveJob
中访问。 我是否需要对此进行任何特殊处理,或者reportingJob
是否也使用了reportingSlaveStepSlaveJob
中的同一个jobExecutionContext
实例?MapExecutionContextDao.java:130
上收到NullPointerException
。 编辑:另请注意,对于第 2 点, slaveJob
无法访问 reportPartitioner 在stepExecutionContext
中添加的值(使用 spring 配置 xml 中#{stepExecutionContext['msbfBatchId']}
reportingPartitioner
)。 stepExecutionContext
中针对键的值显示为null
。
我想为每个分区创建一个新的 reportsOutputListener 实例。 我可以通过将 reportsOutputListener 设置为 Step 范围的 bean 来实现这一点吗?
答案是肯定的。 (如Mahmoud Ben Hassine的评论中所述)
我希望能够访问为reportingJob 创建的相同jobExecutionContext,以便在reportingSlaveJob 中访问。 我是否需要对此进行任何特殊处理,或者reportingSlaveStepSlaveJob 是否也使用了reportingJob 中的同一个jobExecutionContext 实例?
答案是否定的。 我深入研究了Spring 批处理代码,发现JobStep
使用JobParametersExtractor
将值从stepExecutionContext
复制到JobParameters
。 这意味着reportingSlaveJob
可以从JobParameters
而不是StepExecutionContext
访问这些值。 也就是说,出于某种原因, Srping Batch 3.0中的DefaultJobParametersExtractor
实现似乎没有按预期将值复制到jobParameters
。 我最终编写了以下自定义提取器:
public class CustomJobParametersExtractor implements JobParametersExtractor {
private Set<String> keys;
public CustomJobParametersExtractor () {
this.keys = new HashSet<>();
}
@Override
public JobParameters getJobParameters(Job job, StepExecution stepExecution) {
JobParametersBuilder builder = new JobParametersBuilder();
Map<String, JobParameter> jobParameters = stepExecution.getJobParameters().getParameters();
ExecutionContext stepExecutionContext = stepExecution.getExecutionContext();
ExecutionContext jobExecutionContext = stepExecution.getJobExecution().getExecutionContext();
// copy job parameters from parent job to delegate job
for (String key : jobParameters.keySet()) {
builder.addParameter(key, jobParameters.get(key));
}
// copy job/step context from parent job/step to delegate job
for (String key : keys) {
if (jobExecutionContext.containsKey(key)) {
builder.addString(key, jobExecutionContext.getString(key));
} else if (stepExecutionContext.containsKey(key)) {
builder.addString(key, stepExecutionContext.getString(key));
} else if (jobParameters.containsKey(key)) {
builder.addString(key, (String) jobParameters.get(key).getValue());
}
}
return builder.toJobParameters();
}
public void setKeys(String[] keys) {
this.keys = new HashSet<>(Arrays.asList(keys));
}
}
然后我可以在报告从属步骤中使用上述提取器,如下所示:
<step id="reportingSlaveStep" xmlns="http://www.springframework.org/schema/batch">
<job ref="reportingSlaveJob" job-parameters-extractor="customJobParametersExtractor"/>
</step>
其中customJobParametersExtractor
是CustomJobParametersExtractor
类型的 bean,它将我们要复制的所有键传递给reportingSlaveJob
的JobParameters
。
当我运行上述作业时,有时我会收到一个异常说“该作业的作业执行已经在运行”,有时我会在 MapExecutionContextDao.java:130 上收到 NullPointerException
发生这种情况的原因是因为没有我的CustomJobParameterExtractor
, reportingSlaveJob
会以空JobParameters
。 对于Spring 批处理创建新的作业实例,每次启动reportingSlaveJob
的作业参数必须不同。 使用CustomJobParameterExtractor
解决了这个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.