本文介紹了如何從StepExecutionListener After Step方法暫停Spring批處理作業?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我已使用此方法成功地從前一步停止了作業。
public class FirstListener implements StepExecutionListener {
@Override
public void beforeStep(StepExecution stepExecution) {
boolean shouldRun = shouldJobRun();
if (!shouldRun) {
// listeners will still work, but any other step logic (reader, processor, writer) will not happen
stepExecution.setTerminateOnly();
stepExecution.setExitStatus(new ExitStatus("STOPPED", "Job should not be run right now."));
LOGGER.warn(duplicate_message);
}
}
代碼是為了簡潔性/清晰性進行了調整,但這就是要點。調用stepExecution.setTerminateOnly()
和stepExecution.setExitStatus()
就足以讓Spring Batch暫停作業,不執行任何后續步驟。狀態已正確記錄在BATCH_JOB_EXECUTION
表中
EXIT_MESSAGE STATUS
org.springframework.batch.core.JobInterruptedException STOPPED
但是,afterStep
方法中的相同方法會被翻轉,無法識別。狀態被記錄為已完成,并且所有后續步驟都會順其自然地進行(最終以各自可怕的方式失敗,因為After Step中的故障檢測正在檢測故障,因此它們不必這樣做)。
public class SecondListener implements StepExecutionListener {
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
if (stepExecution.getExitStatus().getExitCode().equals(ExitStatus.STOPPED.getExitCode())) {
return stepExecution.getExitStatus();
}
if (everythingIsOkay()) {
return stepExecution.getExitStatus();
}
String failureMessage = "Something bad happened.";
LOGGER.error(failureMessage);
ExitStatus exitStatus = new ExitStatus(ExitStatus.FAILED.getExitCode(), failureMessage);
stepExecution.setExitStatus(exitStatus);
stepExecution.setTerminateOnly();
return exitStatus;
}
這是我能想到的唯一問題:兩個監聽器使用復合監聽器處于同一步驟。
@Bean(name = "org.springframework.batch.core.StepExecutionListener-compositeListener")
@StepScope
public StepExecutionListener compositeListener() {
CompositeStepExecutionListener listener = new CompositeStepExecutionListener();
List<StepExecutionListener> listeners = Lists.newArrayList(secondListener());
if (jobShouldHaveFirstListener()) {
listeners.add(0, firstListener()); // prepend; delegates are called in order
}
listener.setListeners(listeners.toArray());
return listener;
}
public Step firstStep() {
return stepBuilderFactory.get("firstStep")
.listener(compositeListener)
// Small batch size for frequency capping, which happens in the writer, before analytics get written
.<Recipient, Recipient>chunk(500)
.reader(rawRecipientInputFileItemReader)
.processor(recipientItemProcessor)
.writer(recipientWriter)
.throttleLimit(2)
.build();
}
@Bean(name = "org.springframework.batch.core.Job-delivery")
public Job deliveryJob() {
return jobs.get("delivery")
.preventRestart()
.start(firstStep)
.next(deliveryStep)
.next(handleSentStep)
.listener(failedCleanupListener)
.build();
}
是否可以執行其他操作以使此執行正確停止?
推薦答案
經過多次試驗,我發現下面的流定義將允許從步驟偵聽器正確停止作業,而無需在第一步之后執行步驟。
return jobs.get("delivery")
.preventRestart()
.listener(failedCleanupListener)
.flow(firstStep)
.next(deliveryStep)
.next(handleSentStep)
.end()
.build();
主要區別在于將start()
更改為flow()
,并將FlowBuilder.end()
方法調用添加到構建器鏈的末尾。從.start
方法返回的SimpleJobBuilder
類沒有公開類似的end()
方法。
我不知道為什么這會在作業執行的內部造成如此大的差異,我很樂意向能夠說明實際差異是什么以及為什么使用SimpleJobBuilder忽略步驟執行狀態代碼的人提供一些要點。但我發現了一些有用的東西,這就是目前最重要的。
這篇關于如何從StepExecutionListener After Step方法暫停Spring批處理作業?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,