Some batch jobs can be assembled purely from off-the-shelf components
in Spring Batch. For instance the ItemReader and
ItemWriter implementations can be configured to cover
a wide range of scenarios. However, for the majority of cases, custom code
will have to be written. The main API entry points for application
developers are the Tasklet,
ItemReader, ItemWriter and the
various listener interfaces. Most simple batch jobs will be able to use
off-the-shelf input from a Spring Batch ItemReader,
but it is often the case that there are custom concerns in the processing
and writing, which require developers to implement an
ItemWriter or
ItemProcessor.
Here, we provide a few examples of common patterns in custom business
logic. These examples primarily feature the listener interfaces. It should
be noted that an ItemReader or
ItemWriter can implement a listener interface as
well, if appropriate.
A common use case is the need for special handling of errors in a
step, item by item, perhaps logging to a special channel, or inserting a
record into a database. A chunk-oriented Step
(created from the step factory beans) allows users to implement this use
case with a simple ItemReadListener, for errors on
read, and an ItemWriteListener, for errors on
write. The below code snippets illustrate a listener that logs both read
and write failures:
public class ItemFailureLoggerListener extends ItemListenerSupport {
private static Log logger = LogFactory.getLog("item.error");
public void onReadError(Exception ex) {
logger.error("Encountered error on read", e);
}
public void onWriteError(Exception ex, Object item) {
logger.error("Encountered error on write", ex);
}
}
Having implemented this listener it must be registered with the step:
<step id="simpleStep">
...
<listeners>
<listener>
<bean class="org.example...ItemFailureLoggerListener"/>
</listener>
</listeners>
</step>
Remember that if your listener does anything in an
onError() method, it will be inside a transaction that is
going to be rolled back. If you need to use a transactional resource such
as a database inside an onError() method, consider adding a
declarative transaction to that method (see Spring Core Reference Guide
for details), and giving its propagation attribute the value
REQUIRES_NEW.