1

I have a batch job which has to be repeated for a list of items. So I have a "parent" job which uses a batchlet step to load the list and start a child job for each id in the list. Each child job is launched using JobOperator and param using Properties class and this works fine as expected.

I have to retrieve the batch status and wait for the child job to be completed, in order to iterate through the list. I'm trying to get the batch status or exit status using the JobExecution class, however the JobExecution is not retrieving the batch status for the child job.

Instead, I always see the batch status of STARTED, even after the child job completes.

My code looks like:

for (int i = 1; i <= rsList; i++) {
            long execId = jobOperator.start("gah-history-chunk-archive-job",jobParamProperties);
            JobInstance jobInstance = jobOperator.getJobInstance(execId);
            JobExecution jobExecution = jobOperator.getJobExecution(execId);
            logger.info("Instance id: "+jobInstance.getInstanceId());
            while(!jobExecution.getBatchStatus().toString().equals("COMPLETED") || !jobExecution.getBatchStatus().toString().equals("FAILED")) {
                //Both batch status and exit status giving the status of this batchlet, not giving the status of gah-history-chunk-archive-job
logger.info("Batch status is: "+jobExecution.getBatchStatus() +" Thread is sleeping for 5 seconds");
                logger.info("Exit status:"+jobExecution.getExitStatus());

                Thread.sleep(300);
            }
        }

I want to know, how to retrieve batch or exit status of the child job launched from the batchlet. Why do I continue to see a BatchStatus of STARTED?

Scott Kurz
  • 4,985
  • 1
  • 18
  • 40
user3540722
  • 175
  • 1
  • 2
  • 11
  • jobExecution.getBatchStatus() always comes as STARTED even though the child job has completed. – user3540722 Jun 21 '19 at 13:23
  • which implementation product are you using, and in what server environment? Nested batch job execution is not common and so it depends a lot on each implementation. – cheng Jun 21 '19 at 14:03
  • If you are running the same logic on each "child" you should take a good look at "partitions". With a partitioned step, the waiting for the children and the aggregating of the child statuses into the parent job/step status is handled for you by the batch container. This seems like a use case which would map well to this function. – Scott Kurz Jun 24 '19 at 02:36
  • @user3540722 did my answer address the core of your question? I'm thinking of either editing your question a bit and/or posting a new, separate question to explain the point about polling JobExecution vs. BatchStatus. – Scott Kurz Jul 02 '19 at 13:48
  • Seeing my answer was accepted, I rephrased the question and removed less helpful details. Thank you @user3540722 for the question. I think this rework will make it even more helpful to others. – Scott Kurz Jul 09 '19 at 13:46

3 Answers3

1

To "poll" the status of a JobExecution you should obtain a new instance from the JobOperator each time you check its status. So get the JobExecution inside the while-loop, NOT outside.

So it should be more like, for example:

do {
  Thread.sleep(300);

  // log or whatever

  BatchStatus status = jobOperator.getJobExecution(execId).getBatchStatus();

}  while(status != BatchStatus.COMPLETED && status != BatchStatus.FAILED) ;

This is a bit tricky because the behavior here is not standardized by the specification.
Because the spec allows for a diversity of job repository implementations (e.g. database, simple in-memory map, other, ...), it doesn't require a specific behavior for a "cached" JobExecution, and you may find that it "works" some of the time with your original code.

I don't think that what you are actually seeing is the "parent" object instance being returned; I suspect you may just be getting confused by not seeing what you expected.

In any case, to have your code be more portable, obtain the JobExecution with each status check.

Scott Kurz
  • 4,985
  • 1
  • 18
  • 40
  • Won't there be a problem if the job gets into the status [ABANDONED](https://docs.oracle.com/javaee/7/api/javax/batch/runtime/BatchStatus.html#ABANDONED), e.g.? – metters Jul 10 '19 at 07:35
  • 1
    Good point. Job end/termination could also include STOPPED or ABANDONED states. Depending on the use case you may or may not want to include those two (which one often has more control over). But I was treating the question as "how to poll" in general, not so much "how to poll for job end", so the key point is to not rely on a single JobExecution instance. – Scott Kurz Jul 10 '19 at 14:15
0

JobExecution points to the parent job, even though its been setup with the child job execution id. Not sure why batch behaves in this way.

JobExecution jobExecution = jobOperator.getJobExecution(execId);
jobExecution.getBatchStatus(); //Parent job status

But If we go with the BatchRuntime class, we can get the corresponding job, batch status. This helps me to get the child job status and can loop to the next batch launch.

//Returns the child job status as expected
BatchRuntime.getJobOperator().getJobExecution(execId).getBatchStatus();

user3540722
  • 175
  • 1
  • 2
  • 11
  • Should this not be part of the information given in the question or is this an answer to your own question? Sorry, but I'm a bit confused here. – metters Jun 26 '19 at 07:16
0

I would recommend to poll the Exitstatus of the job instead of the BatchStatus itself:

for (int i = 1; i <= rsList; i++) {
    long execId = jobOperator.start("gah-history-chunk-archive-job",jobParamProperties);
    JobInstance jobInstance = jobOperator.getJobInstance(execId);
    JobExecution jobExecution = jobOperator.getJobExecution(execId);
    logger.info("Instance id: "+jobInstance.getInstanceId());
    while(jobExecution.getExitStatus() == null) {
        //do your logging etc.   
        Thread.sleep(300);
    }
}
metters
  • 533
  • 1
  • 8
  • 17