170 lines
17 KiB
HTML
170 lines
17 KiB
HTML
<html><head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
|
<title>8. Repeat</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="index.html" title="Spring Batch - Reference Documentation"><link rel="up" href="index.html" title="Spring Batch - Reference Documentation"><link rel="prev" href="scalability.html" title="7. Scaling and Parallel Processing"><link rel="next" href="retry.html" title="9. Retry"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">8. Repeat</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="scalability.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="retry.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="repeat" href="#repeat"></a>8. Repeat</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="repeatTemplate" href="#repeatTemplate"></a>8.1 RepeatTemplate</h2></div></div></div><p>Batch processing is about repetitive actions - either as a simple
|
|
optimization, or as part of a job. To strategize and generalize the
|
|
repetition as well as to provide what amounts to an iterator framework,
|
|
Spring Batch has the <code class="classname">RepeatOperations</code> interface.
|
|
The <code class="classname">RepeatOperations</code> interface looks like
|
|
this:</p><pre class="programlisting"><span class="hl-keyword">public</span> <span class="hl-keyword">interface</span> RepeatOperations {
|
|
|
|
RepeatStatus iterate(RepeatCallback callback) <span class="hl-keyword">throws</span> RepeatException;
|
|
|
|
}</pre><p>The callback is a simple interface that allows you to insert
|
|
some business logic to be repeated:</p><pre class="programlisting"><span class="hl-keyword">public</span> <span class="hl-keyword">interface</span> RepeatCallback {
|
|
|
|
RepeatStatus doInIteration(RepeatContext context) <span class="hl-keyword">throws</span> Exception;
|
|
|
|
}</pre><p>The callback is executed repeatedly until the implementation
|
|
decides that the iteration should end. The return value in these
|
|
interfaces is an enumeration that can either be
|
|
<code class="code">RepeatStatus.CONTINUABLE</code> or
|
|
<code class="code">RepeatStatus.FINISHED</code>. A <code class="classname">RepeatStatus</code>
|
|
conveys information to the caller of the repeat operations about whether
|
|
there is any more work to do. Generally speaking, implementations of
|
|
<code class="classname">RepeatOperations</code> should inspect the
|
|
<code class="classname">RepeatStatus</code> and use it as part of the decision to
|
|
end the iteration. Any callback that wishes to signal to the caller that
|
|
there is no more work to do can return
|
|
<code class="code">RepeatStatus.FINISHED</code>.</p><p>The simplest general purpose implementation of
|
|
<code class="classname">RepeatOperations</code> is
|
|
<code class="classname">RepeatTemplate</code>. It could be used like this:</p><pre class="programlisting">RepeatTemplate template = <span class="hl-keyword">new</span> RepeatTemplate();
|
|
|
|
template.setCompletionPolicy(<span class="hl-keyword">new</span> FixedChunkSizeCompletionPolicy(<span class="hl-number">2</span>));
|
|
|
|
template.iterate(<span class="hl-keyword">new</span> RepeatCallback() {
|
|
|
|
<span class="hl-keyword">public</span> ExitStatus doInIteration(RepeatContext context) {
|
|
<span class="hl-comment">// Do stuff in batch...</span>
|
|
<span class="hl-keyword">return</span> ExitStatus.CONTINUABLE;
|
|
}
|
|
|
|
});</pre><p>In the example we return <code class="code">RepeatStatus.CONTINUABLE</code> to
|
|
show that there is more work to do. The callback can also return
|
|
<code class="code">ExitStatus.FINISHED</code> if it wants to signal to the caller that
|
|
there is no more work to do. Some iterations can be terminated by
|
|
considerations intrinsic to the work being done in the callback, others
|
|
are effectively infinite loops as far as the callback is concerned and the
|
|
completion decision is delegated to an external policy as in the case
|
|
above.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="repeatContext" href="#repeatContext"></a>8.1.1 RepeatContext</h3></div></div></div><p>The method parameter for the <code class="classname">RepeatCallback</code>
|
|
is a <code class="classname">RepeatContext</code>. Many callbacks will simply
|
|
ignore the context, but if necessary it can be used as an attribute bag
|
|
to store transient data for the duration of the iteration. After the
|
|
<code class="methodname">iterate</code> method returns, the context will no
|
|
longer exist.</p><p>A <code class="classname">RepeatContext</code> will have a parent context
|
|
if there is a nested iteration in progress. The parent context is
|
|
occasionally useful for storing data that need to be shared between
|
|
calls to <code class="methodname">iterate</code>. This is the case for instance
|
|
if you want to count the number of occurrences of an event in the
|
|
iteration and remember it across subsequent calls.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="repeatStatus" href="#repeatStatus"></a>8.1.2 RepeatStatus</h3></div></div></div><p><code class="classname">RepeatStatus</code> is an enumeration used by
|
|
Spring Batch to indicate whether processing has finished. These are
|
|
possible <code class="classname">RepeatStatus</code> values:</p><div class="table"><a name="d5e3224" href="#d5e3224"></a><p class="title"><b>Table 8.1. ExitStatus Properties</b></p><div class="table-contents"><table summary="ExitStatus Properties" style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col><col></colgroup><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; "><span class="bold"><strong>Value</strong></span></td><td style="border-bottom: 0.5pt solid ; "><span class="bold"><strong>Description</strong></span></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; ">CONTINUABLE</td><td style="border-bottom: 0.5pt solid ; ">There is more work to do.</td></tr><tr><td style="border-right: 0.5pt solid ; ">FINISHED</td><td style="">No more repetitions should take place.</td></tr></tbody></table></div></div><br class="table-break"><p><code class="classname">RepeatStatus</code> values can also be combined
|
|
with a logical AND operation using the <code class="methodname">and</code>()
|
|
method in <code class="classname">RepeatStatus</code>. The effect of this is to
|
|
do a logical AND on the continuable flag. In other words, if either
|
|
status is <code class="code">FINISHED</code>, then the result will be
|
|
<code class="code">FINISHED</code>.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="completionPolicies" href="#completionPolicies"></a>8.2 Completion Policies</h2></div></div></div><p>Inside a <code class="classname">RepeatTemplate</code> the termination of
|
|
the loop in the <code class="methodname">iterate</code> method is determined by a
|
|
<code class="classname">CompletionPolicy</code> which is also a factory for the
|
|
<code class="classname">RepeatContext</code>. The
|
|
<code class="classname">RepeatTemplate</code> has the responsibility to use the
|
|
current policy to create a <code class="classname">RepeatContext</code> and pass
|
|
that in to the <code class="classname">RepeatCallback</code> at every stage in the
|
|
iteration. After a callback completes its
|
|
<code class="methodname">doInIteration</code>, the
|
|
<code class="classname">RepeatTemplate</code> has to make a call to the
|
|
<code class="classname">CompletionPolicy</code> to ask it to update its state
|
|
(which will be stored in the <code class="classname">RepeatContext</code>). Then
|
|
it asks the policy if the iteration is complete.</p><p>Spring Batch provides some simple general purpose implementations of
|
|
<code class="classname">CompletionPolicy</code>. The
|
|
<code class="classname">SimpleCompletionPolicy</code> just allows an execution up
|
|
to a fixed number of times (with <code class="code">RepeatStatus.FINISHED</code>
|
|
forcing early completion at any time).</p><p>Users might need to implement their own completion policies for more
|
|
complicated decisions. For example, a batch processing window that
|
|
prevents batch jobs from executing once the online systems are in use
|
|
would require a custom policy.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="repeatExceptionHandling" href="#repeatExceptionHandling"></a>8.3 Exception Handling</h2></div></div></div><p>If there is an exception thrown inside a
|
|
<code class="classname">RepeatCallback</code>, the
|
|
<code class="classname">RepeatTemplate</code> consults an
|
|
<code class="classname">ExceptionHandler</code> which can decide whether or not to
|
|
re-throw the exception.</p><pre class="programlisting"><span class="hl-keyword">public</span> <span class="hl-keyword">interface</span> ExceptionHandler {
|
|
|
|
<span class="hl-keyword">void</span> handleException(RepeatContext context, Throwable throwable)
|
|
<span class="hl-keyword">throws</span> RuntimeException;
|
|
|
|
}</pre><p>A common use case is to count the number of exceptions of a
|
|
given type, and fail when a limit is reached. For this purpose Spring
|
|
Batch provides the <code class="classname">SimpleLimitExceptionHandler</code> and
|
|
slightly more flexible
|
|
<code class="classname">RethrowOnThresholdExceptionHandler</code>. The
|
|
<code class="classname">SimpleLimitExceptionHandler</code> has a limit property
|
|
and an exception type that should be compared with the current exception -
|
|
all subclasses of the provided type are also counted. Exceptions of the
|
|
given type are ignored until the limit is reached, and then rethrown.
|
|
Those of other types are always rethrown.</p><p>An important optional property of the
|
|
<code class="classname">SimpleLimitExceptionHandler</code> is the boolean flag
|
|
<code class="code">useParent</code>. It is false by default, so the limit is only
|
|
accounted for in the current <code class="classname">RepeatContext</code>. When
|
|
set to true, the limit is kept across sibling contexts in a nested
|
|
iteration (e.g. a set of chunks inside a step).</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="repeatListeners" href="#repeatListeners"></a>8.4 Listeners</h2></div></div></div><p>Often it is useful to be able to receive additional callbacks for
|
|
cross cutting concerns across a number of different iterations. For this
|
|
purpose Spring Batch provides the <code class="classname">RepeatListener</code>
|
|
interface. The <code class="classname">RepeatTemplate</code> allows users to
|
|
register <code class="classname">RepeatListener</code>s, and they will be given
|
|
callbacks with the <code class="classname">RepeatContext</code> and
|
|
<code class="classname">RepeatStatus</code> where available during the
|
|
iteration.</p><p>The interface looks like this:</p><pre class="programlisting"><span class="hl-keyword">public</span> <span class="hl-keyword">interface</span> RepeatListener {
|
|
<span class="hl-keyword">void</span> before(RepeatContext context);
|
|
<span class="hl-keyword">void</span> after(RepeatContext context, RepeatStatus result);
|
|
<span class="hl-keyword">void</span> open(RepeatContext context);
|
|
<span class="hl-keyword">void</span> onError(RepeatContext context, Throwable e);
|
|
<span class="hl-keyword">void</span> close(RepeatContext context);
|
|
}</pre><p>The <code class="methodname">open</code> and
|
|
<code class="methodname">close</code> callbacks come before and after the entire
|
|
iteration. <code class="methodname">before</code>, <code class="methodname">after</code>
|
|
and <code class="methodname">onError</code> apply to the individual
|
|
RepeatCallback calls.</p><p>Note that when there is more than one listener, they are in a list,
|
|
so there is an order. In this case <code class="methodname">open</code> and
|
|
<code class="methodname">before</code> are called in the same order while
|
|
<code class="methodname">after</code>, <code class="methodname">onError</code> and
|
|
<code class="methodname">close</code> are called in reverse order.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="repeatParallelProcessing" href="#repeatParallelProcessing"></a>8.5 Parallel Processing</h2></div></div></div><p>Implementations of <code class="classname">RepeatOperations</code> are not
|
|
restricted to executing the callback sequentially. It is quite important
|
|
that some implementations are able to execute their callbacks in parallel.
|
|
To this end, Spring Batch provides the
|
|
<code class="classname">TaskExecutorRepeatTemplate</code>, which uses the Spring
|
|
<code class="classname">TaskExecutor</code> strategy to run the
|
|
<code class="classname">RepeatCallback</code>. The default is to use a
|
|
<code class="classname">SynchronousTaskExecutor</code>, which has the effect of
|
|
executing the whole iteration in the same thread (the same as a normal
|
|
<code class="classname">RepeatTemplate</code>).</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="declarativeIteration" href="#declarativeIteration"></a>8.6 Declarative Iteration</h2></div></div></div><p>Sometimes there is some business processing that you know you want
|
|
to repeat every time it happens. The classic example of this is the
|
|
optimization of a message pipeline - it is more efficient to process a
|
|
batch of messages, if they are arriving frequently, than to bear the cost
|
|
of a separate transaction for every message. Spring Batch provides an AOP
|
|
interceptor that wraps a method call in a
|
|
<code class="classname">RepeatOperations</code> for just this purpose. The
|
|
<code class="classname">RepeatOperationsInterceptor</code> executes the
|
|
intercepted method and repeats according to the
|
|
<code class="classname">CompletionPolicy</code> in the provided
|
|
<code class="classname">RepeatTemplate</code>.</p><p>Here is an example of declarative iteration using the Spring AOP
|
|
namespace to repeat a service call to a method called
|
|
<code class="methodname">processMessage</code> (for more detail on how to
|
|
configure AOP interceptors see the Spring User Guide):</p><pre class="programlisting"><span class="hl-tag"><aop:config></span>
|
|
<span class="hl-tag"><aop:pointcut</span> <span class="hl-attribute">id</span>=<span class="hl-value">"transactional"</span>
|
|
<span class="hl-attribute">expression</span>=<span class="hl-value">"execution(* com..*Service.processMessage(..))"</span><span class="hl-tag"> /></span>
|
|
<span class="hl-tag"><aop:advisor</span> <span class="hl-attribute">pointcut-ref</span>=<span class="hl-value">"transactional"</span>
|
|
<span class="hl-attribute">advice-ref</span>=<span class="hl-value">"retryAdvice"</span> <span class="hl-attribute">order</span>=<span class="hl-value">"-1"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></aop:config></span>
|
|
|
|
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"retryAdvice"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.spr...RepeatOperationsInterceptor"</span><span class="hl-tag">/></span></pre><p>The example above uses a default
|
|
<code class="classname">RepeatTemplate</code> inside the interceptor. To change
|
|
the policies, listeners etc. you only need to inject an instance of
|
|
<code class="classname">RepeatTemplate</code> into the interceptor.</p><p>If the intercepted method returns <code class="code">void</code> then the
|
|
interceptor always returns ExitStatus.CONTINUABLE (so there is a danger of
|
|
an infinite loop if the <code class="classname">CompletionPolicy</code> does not
|
|
have a finite end point). Otherwise it returns
|
|
<code class="code">ExitStatus.CONTINUABLE</code> until the return value from the
|
|
intercepted method is null, at which point it returns
|
|
<code class="code">ExitStatus.FINISHED</code>. So the business logic inside the target
|
|
method can signal that there is no more work to do by returning
|
|
<code class="code">null</code>, or by throwing an exception that is re-thrown by the
|
|
<code class="classname">ExceptionHandler</code> in the provided
|
|
<code class="classname">RepeatTemplate</code>.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="scalability.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="retry.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">7. Scaling and Parallel Processing </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 9. Retry</td></tr></table></div></body></html> |