WebSphere Application Server & Liberty

Jakarta Batch Post 132: Apache BatchEE - ChainProcessor/ChainBatchlet

By David Follis posted Thu April 08, 2021 09:31 AM

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 iTunesGoogle PlayStitcher, or use the link to the RSS feed

The first BatchEE extension we’ll look at is the ChainProcessor and ChainBatchlet.  These are located in the extensions/extras folder and are in the org.apache.batchee.extras.chain package.

As you’d expect, ChainProcessor implements the standard ItemProcessor interface and ChainBatchlet implements the standard Batchlet interface.  Which means the processor has a processItem method and the batchlet has an invoke method. 

Before we get into what they do, we also need to note that both classes Extend the locally defined Chain class.  Because they extend that class, it can have batch properties injected into it (if it was just some other object the properties would have to be injected into both the processor and batchlet – this keeps it all in the common Chain code).  Let’s look at what Chain does.

It actually gets four properties injected, but we’ll focus on just one:  chain.  This is (by default) a comma separated list of classes that implement ItemProcessor or Batchlet that are to be called, in the order specified.  The code parses the list apart and new’s up an instance of each one.  As we’ve noted before, the Processor and Batchlet interfaces don’t have any sort of ‘open’ method to do initialization and batch properties don’t get injected until after the constructor has run, so all this just has to happen as part of the initial invocation.  Doesn’t really matter for a batchlet, but the processor will be called a lot and we have to have conditional logic around the initialization so we only do it once.

Anyway, after we’ve found and created all the objects you specified in the chain list, their process or invoke methods are called, in the order you specified them. 

What about the results?  An ItemProcessor is expected to return some sort of result object that will be given to the ItemWriter.  In the case of a ChainProcessor that’s the returned value from the last ItemProcessor in the list.  So order matters.  Each processor implementation will be given the same object provided by the ItemReader, but only the returned result of the last processor makes it to the writer.

In the case of a Batchlet, the process method is expected to return a string which becomes the exit status for the step, so the results of the last Batchlet implementation called is cast to a String and returned. 

What happens if an exception is thrown?  As written there’s no catch logic so any exception thrown by any processor/batchlet implementation will just fail the step right there.  You’d want to catch and handle any likely exceptions inside your implementations.

This seems like it could be pretty useful, although you’d have to be careful that any-but-the-last implementation doesn’t expect its returned results to be used.