I have a (very simple) java batch job in JDL with just two steps.
When the step "download" return the status "STOPPED" the job should stop. After restart the stop notify should be called.
Without the partition everything works fine.
stats without partition
after step=download batchStatus=COMPLETED exitStatus=STOPPED
after job=job batchStatus=STOPPED exitStatus=STOPPED
With partition i get realy strange stati for batch end exit. And the job doesn't stop if the download step returns "STOPPED". Even if the partition has just one thread and one partition.
When trying to restart the following error is raised (of course). JBERET000609: Job execution 1 has already completed and cannot be restarted.
stats with partition
after step=download batchStatus=STARTED exitStatus=null
after job=job batchStatus=COMPLETED exitStatus=COMPLETED
job descrition
<job id="job" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0" restartable="true">
<step id="download" next="notify">
<batchlet ref="downloadBatchlet">
</batchlet>
<partition>
<mapper ref="basicPartition" />
</partition>
<stop on="STOPPED" restart="notify"/>
</step>
<step id="notify">
<batchlet ref="notifyBatchlet"></batchlet>
<end on="COMPLETED"/>
</step>
</job>
Every hint an suggestions are welcome. What I am missing?
Without partition
On job start the job calls the - downloadBatchlet => STOPPED and stopps.
On restart the job calls the - notifyBatchlet => COMPLETED and ends.
With partition
On job start the job calls the - downloadBatchlet => STOPPED and stopps.
On restart the job calls NO STEPS and ends.
@Named
public class DownloadBatchlet extends AbstractBatchlet {
@Override
public String process() throws Exception {
return BatchStatus.STOPPED.toString();
}
@Override
public void stop() throws Exception {
}
}
In Java Batch, there is a separate batch and exit status for the step itself and also for each partition.
Since "transitioning" (to the next step, or for stopping the job, in your case) occurs at the job level here, you would need to set a non-default exit status at the "top level" of the step, not merely at the level of each partition.
If you want to include logic which reacts to each partition's status, a good starting point would be the PartitionAnalyzer#analyzeStatus method, which is called as each partition terminates. This runs on the "top level" thread (as does the PartitionReducer).
public class MyPartitionAnalyzer extends AbstractPartitionAnalyzer {
@Inject
private StepContext stepCtx;
@Override
public void analyzeStatus(BatchStatus batchStatus, String exitStatus) throws Exception {
// Overrides default exit status if non-COMPLETED partition seen
if (!exitStatus.equals(BatchStatus.COMPLETED)) {
stepCtx.setExitStatus(exitStatus);
}
}
}
You can use whatever logic you want to react (or not) to the partitions' batch and exit statuses. The key here is that the analyzer runs on the top-level step thread, and so sets the step-level status. The batchlet's return value, on the other hand, only sets the partition-level status.
The analyzer can be used to "aggregate" partition-level status however you want. If you do nothing, the step-level exit status defaults to the step-level batch status, so if the step completes normally the step level exit status is COMPLETED.