Search code examples
javaspring-bootspring-integrationspring-batchspring-integration-dsl

How to guarantee that job is finished before starting the next step of IntegrationFlow?


I have following flow declaration:

return flow -> flow.handle(myHandler)                
                .handle(springBatchJobLauncher)              
                .gateway(acknowledgementFlow);

launcher looks like this:

@ServiceActivator
public JobExecution launch(JobLaunchRequest request) throws JobExecutionException {
    Job job = request.getJob();
    JobParameters jobParameters = request.getJobParameters();

    return jobLauncher.run(job, jobParameters);
}

I need to start acknowledgementFlow as soon as job started by springBatchJobLauncher is finished. Is it guaranteed according this configuration?


Solution

  • Let's take a look into the JobLauncher.run() JavaDocs!

     * Start a job execution for the given {@link Job} and {@link JobParameters}
     * . If a {@link JobExecution} was able to be created successfully, it will
     * always be returned by this method, regardless of whether or not the
     * execution was successful. If there is a past {@link JobExecution} which
     * has paused, the same {@link JobExecution} is returned instead of a new
     * one created. A exception will only be thrown if there is a failure to
     * start the job. If the job encounters some error while processing, the
     * JobExecution will be returned, and the status will need to be inspected.
    

    So, if job has started successfully, you'll get a JobExecution object, but this indeed doesn't matter that your job has finished or not. For that goal I believe we need to have something like JobExecutionListener hook.

    See more info in the Spring Batch Docs: https://docs.spring.io/spring-batch/4.2.x/reference/html/spring-batch-integration.html#providing-feedback-with-informational-messages

    There is a sample for the step:

    @MessagingGateway(name = "notificationExecutionsListener", defaultRequestChannel = "stepExecutionsChannel")
    public interface NotificationExecutionListener extends StepExecutionListener {}
    

    But the same approach can be applied for the JobExecutionListener.

    So, you need to devid your flow two several and have your .gateway(acknowledgementFlow) called only from the afterJob(JobExecution jobExecution) is executed from your job.