In Parts I and II of Spring Batch Concepts we covered first the construction and layout of our Batch Module, then we looked at how to add Job parameters and launch a specific Job from the command line. In this post we're going to look at the Job itself and sharing data across Job processes.
We've seen the module layout before, shown again here because the DemoJob classes each have a role to play in our discussion. We see DemoJobCondition at the top of the class list. In our previous post we discussed how we're using the Condition class to determine if we launch DemoJob. DemoJobConfiguration is our primary class which builds the Job and Steps. The DemoJobItemProcessor is the “Action Class” which processes the data from the Reader and afterward passes it off to the Writer. Our Job and Step Listener classes allow us to monitor the processing and perform additional actions with the data. DemoJobRunner kicks off the job with any parameters or iteration settings we provide. We listed the Runner class in Part II.
It would be helpful to know what our DemoJob is going to do. It's going to read NixMash Spring Posts from MySQL using a JpaPagingItemReader, then it will take the Post Titles, capitalize them and write the titles to a CSV file. The Job is scheduled to repeat itself every 20 seconds.
ALSO, we are going to capture each PostId value along the way. At the end of the job we're going to display the last PostId value processed. For kicks we also have an optional Job Step which we're going to run only twice, based on a Job property we added in an External Properties File.
Here's the DemoJob log output.
We're going to capture the PostId of each Post read in the Job Step. Let's first take a quick look at our StepBuilder logic. Notice the primary activities: read, process and write. We add a Step Listener to grab the PostId when the Step completes. Because we need to retrieve that PostId from various processes we need to add a promotionListener Bean.
Our DemoJobStepListener captures our PostId from each Read and places it into the Job ExecutionContext as you see below. We added logging to confirm that we're capturing each Post object read.
We're going to display the last processed PostId value when the job ends and use it elsewhere in the job, so we need to make it shareable by creating a key for it in the ExecutionContext. That's the role of the PromotionListener Bean.
If we didn't promote our PostId key our Job output would look like this, with Null exceptions and null value for PostId when the Job ends.
We'll cover Jobflow Decision-making in our next Spring Batch Concepts post, so stay tuned.