![](/img/trans.png)
[英]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.