4.4. Application Tier
4.4.1.7. Intercepting Step Execution
Just as with theJob, there are many events during the execution of aStepthat a user may need notification of.
For example, if writing out to a flat file that requires a footer, theItemWriter needs to be notified when the Stephas been completed, so that it can write the footer. This can be accomplished with one of many Step
scoped listeners.
4.4.1.7.1. StepExecutionListener
StepExecutionListener represents the most generic listener for Step execution. It allows for notification
before aStepis started, after it has completed, and if any errors are encountered during processing:
public interface StepExecutionListener extends StepListener { void beforeStep(StepExecution stepExecution);
ExitStatus onErrorInStep(StepExecution stepExecution, Throwable e); ExitStatus afterStep(StepExecution stepExecution);
ExitStatusis the return type ofonErrorInStepandafterStepin order to allow listeners the chance to modify
the exit code that is returned upon completion of aStep. AStepExecutionListenercan be applied to any step
factory bean via the listeners property:
<bean id="simpleStep"
class="org.springframework.batch.core.step.item.SimpleStepFactoryBean" > <property name="transactionManager" ref="transactionManager" />
<property name="jobRepository" ref="jobRepository" /> <property name="itemReader" ref="itemReader" /> <property name="itemWriter" ref="itemWriter" /> <property name="commitInterval" value="10" /> <property name="listeners" ref="stepListener" /> </bean>
Because all listeners extend theStepListenerinterface, they all may be applied to factory beans in the same
way.
4.4.1.7.2. ChunkListener
A chunk is defined as the items processed within the scope of a transaction. Committing a transaction commits a 'chunk'. It may be useful to be nofied before and after a chunk has completed, in which case the
ChunkListenerinterface may be used:
public interface ChunkListener extends StepListener { void beforeChunk();
void afterChunk(); }
ThebeforeChunkmethod is called after the transaction is started, but beforereadis called on theItemReader.
Conversely,afterChunkis called after the last call towriteon theItemWriter, but before the chunk has been
committed.
4.4.1.7.3. ItemReadListener
When discussing skip logic above, it was mentioned that it may be beneficial to log out skipped records, so that they can be deal with later. In the case of read errors, this can be done with anItemReaderListener:
public interface ItemReadListener extends StepListener { void beforeRead();
void afterRead(Object item); void onReadError(Exception ex); }
ThebeforeReadmethod will be called before each call toreadon theItemReader. TheafterReadmethod will
be called after each successful call toread, and will be passed the item that was read. If there was an error
while reading, theonReadErrormethod will be called. The exception encounterd will be provided so that it can
be logged.
4.4.1.7.4. ItemWriteListener
Just as with the ItemReaderListener, the writing of an item can be 'listened' to:
public interface ItemWriteListener extends StepListener { void beforeWrite(Object item);
void afterWrite(Object item);
void onWriteError(Exception ex, Object item); }
ThebeforeWritemethod will be called beforewriteon the ItemWriter, and is handed the item that will be
written. TheafterWritemethod will be called after the item has been succesfully writen. If there was an error
while writing, the onWriteError method will be called. The exception encountered and the item that was
attempted to be written will be provided, so that they can be logged.
4.4.2. TaskletStep
ItemOriented processing is not the only way to process in aStep. What if aStepmust consist as a simple storec
procedure call? You could implement the call as anItemReaderand return null after the procedure finishes, but
it is a bit unnatural since there would need to be a no-op ItemWriter and lots of overhead for transaction
handling, listeners, etc. Spring Batch provides an implementation ofStepfor this scenario: TaskletStep. As
explained in Chapter 2, theTaskletis a simple interface that has one method,execute, which will be a called
once for the wholeStep.Tasklet implementors might call a stored procedure, a script, or a simple SQL upate
statement. Because there are less concerns, there are only two required dependencies for a TaskletStep: a Tasklet, and aJobRepository:
<bean id="taskletStep"
class="org.springframework.batch.core.step.tasklet.TaskletStep" /> <property name="tasklet" ref="tasklet" />
<property name="jobRepository" ref="repository" /> </bean>
4.4.2.1. TaskletAdapter
As with other adapters for the ItemWriter and ItemReader interfaces, the Tasklet interface contains an
implementation that allows for adapting itself to any pre-existing class:TaskletAdapter. An example where
this may be useful is an existing DAO that is used to upate a flag on a set of records. TheTaskletAdaptercan
be used to call this class without having to write an adapter for theTaskletinterface:
<bean id="deleteFilesInDir" parent="taskletStep"> <property name="tasklet">
<bean class="org.springframework.batch.core.step.tasklet.TaskletAdapter"> <property name="targetObject">
<bean class="org.mycompany.FooDao"> </property>
<property name="targetMethod" value-"updateFoo" /> </bean>
</property> </bean>