This post is part of a series delving into the details of the JSR-352 (Java Batch) specification. Each post examines a very specific part of the specification and looks at how it works and how you might use it in a real batch application.To start at the beginning, follow the link to the first post.
The next post in the series is here
.This series is also available as a podcast on iTunes, Google Play, Stitcher, or use the link to the RSS feed.
Last time we talked about the split/flow concept that allows you to run multiple different steps concurrently in the same job. We spent a lot of time focusing on how control is managed between steps in each flow and what happens when all the flows are complete. But then what?
If you recall, we said that you can specify a next element to get control when the split is complete. This is an unconditional flow of control. A lot of different things might have happened in the flows that are within the split. There’s probably some sort of complex decision that needs to be made to figure out what to do next. A decision that needs to consider what happened in every flow, all at once. For that we have….a decider.
If the split indicates the next thing to get control is an element called a decider then the batch container will give control to an implementation of the Decider interface. Technically you can have a decision element anywhere you can have a step, but it is most interesting right after a split.
The decider has one method called decide. It gets passed an array consisting of the StepExecution objects for the final step in each flow contained in the split. The StepExecution has methods that allow you access to information about the step, but the most interesting one in this case is the exit status value for the step.
The idea is that each flow will have a final step that will somehow summarize the results of the flow into a String that gets set as the exit status for that step. Then the decider can look at the final result of each flow and reach some sort of conclusion about where to go next. You can also get the step name in case that helps you interpret the exit status.
The return value from the decide method becomes the exit status used for conditional flow control in the JSL. That means part of the decider element in the JSL will include ‘on’ exit status value ‘to’ some other step for the different possible values returned from the decider. Coordination between the values in the code and the JSL is required for this to work.
You might be tempted to try to use the StepContext to set an exit status for the decider, but it turns out a decider doesn’t actually have a StepContext because it isn’t really a step.
Another interesting consequence of using a decider is that the return value from the decide method becomes the current value for the Job Exit Status. A couple of weeks ago we talked about setting that and here’s another way it can get set. Be careful about this if your logic to set the Job Exit Status depends on code that makes sure it isn’t already set. A decider might set it for you.
Our sample code is a simple split with three flows. Each flow uses a new Batchlet called BatchletSetExitStatusToParm which allows us to force the Step Exit Status for each flow to a different value without having three different batchlets. Just a shortcut because it is a sample that doesn’t do anything real. The decider is called SampleDecider. The JSL for the job is in UsingADecider.xml. Have a look…steal some code.
The sample parts are here: https://github.com/follisd/batch-samples