我们已经单步配置了批处理作业。一般结构如,
<batch:job id="mainJob">
<batch:step id="step1">
<batch:tasklet>
<batch:chunk reader="fileReader" writer="jmsItemWriter" >
<batch:retryable-exception-classes>
<batch:include class="org.springframework.dao.CannotAcquireLockException"/>
</batch:retryable-exception-classes>
</batch:chunk>
</batch:tasklet>
<batch:end on="UNKNOWN"/>
<batch:next on="*" to="step1"/>
<batch:listeners>
<batch:listener ref="listener1"/>
<batch:listener ref="listener2"/>
</batch:listeners>
</batch:step>
<batch:listeners>
<batch:listener ref="jobListener"/>
</batch:listeners>
</batch:job>
fileReader是FlatFileItemReader,它逐行读取文件并将每一行传递给&#39; listener2&#39;。在listener2中,如果行中有错误,则应将状态设置为“未知”。 (没有失败,因为工作不应该再次开始)然后停止工作。
要做到这一点,我们有。
<batch:end on="UNKNOWN"/>
<batch:next on="*" to="step1"/>
但批处理作业不会以未知结束并因为下一步而进入循环。如果&#39; next&#39;则会有例外。没有提到。
我们如何解决这个问题?
编辑:
对Dean的回答有更多解释。
Listener2逐行获取FieldSet即文件条目。处理这些条目时,如果满足某些条件(也涉及数据库查询),则作业不应读取更多文件并停止。由于处理是在覆盖方法中完成的,因此mapFieldSet&#39;它不会抛出任何异常,不能使用新的异常,返回null只读取下一行。通常,文件有数千行,但在前2行中,确定是否需要进一步读取。
答案 0 :(得分:0)
你所做的非常不合标准。这就是我要做的......
ItemProcessor
中进行,而不是等待JMS编写器失败StepExecutionListener
),用于检查失败异常并翻转ExitStatus
示例步骤执行侦听器afterStep
方法:
public ExitStatus afterStep(StepExecution stepExecution) {
for (Throwable t : stepExecution.getFailureExceptions()) {
if ("EXPECTED MESSAGE".equals(t.getMessage())) {
return ExitStatus.UNKNOWN;
}
}
return null;
}
根据问题中的新信息进行更新
根据您的指示,似乎Decider
可能实际上是您最干净的解决方案。
对工作流程的修改:
<batch:job id="mainJob">
<batch:decision id="decision" decider="someDecider">
<next on="PROCESS" to="step1" />
<end on="STOP" />
<fail on="*" />
</batch:decision>
<batch:step id="step1">
<!-- . . . -->
</batch:step>
<!-- . . . -->
</batch:job>
示例Decider
类:
public class ProcessFileDecider implements JobExecutionDecider {
private Resource resource;
@Override
public FlowExecutionStatus decide(final JobExecution jobExecution, final StepExecution stepExecution) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()))) {
final String lineOne = reader.readLine();
final String lineTwo = (lineOne != null) ? reader.readLine() : null;
final boolean processFile = true; //some logic here
if (processFile) {
return new FlowExecutionStatus("PROCESS");
}
return new FlowExecutionStatus("STOP");
} catch (final IOException e) {
throw new IllegalStateException("Hit error deciding whether to process the resource!", e);
}
}
public void setResource(Resource resource) {
this.resource = resource;
}
}