Spelling and grammar corrections to the docs.

This commit is contained in:
lucasward
2009-01-29 22:38:25 +00:00
parent cd3117e1d9
commit 2882420737
10 changed files with 137 additions and 135 deletions

View File

@@ -87,7 +87,7 @@
</imageobject>
</mediaobject>
<para>In Spring Batch, a Job is simply a continer for Steps. It combines
<para>In Spring Batch, a Job is simply a container for Steps. It combines
multiple steps that belong logically together in a flow and allows for
configuration of properties global to all steps, such as restartability.
The job configuration contains:</para>
@@ -110,7 +110,7 @@
interface is provided by Spring Batch in the form of the
<classname>SimpleJob</classname> class which creates some standard
functionality on top of <classname>Job</classname>, however the batch
namespace abstracts away the need to instaniate it directly. Instead, the
namespace abstracts away the need to instantiate it directly. Instead, the
<code>&lt;job&gt;</code> tag can be used:</para>
<programlisting>
@@ -151,7 +151,7 @@
likely be a business decision, it is left up to the
<classname>ItemReader</classname> to decide. What using the same
<classname>JobInstance</classname> will determine, however, is whether
or not the 'state' (i.e. the ExecutionContext, which is discussed below)
or not the 'state' (i.e. The ExecutionContext, which is discussed below)
from previous executions will be used. Using a new
<classname>JobInstance</classname> will mean 'start from the beginning'
and using an existing instance will generally mean 'start from where you
@@ -756,7 +756,7 @@
<entry>schedule.Date</entry>
<entry>2008-01-01 </entry>
<entry>2008-01-01</entry>
</row>
</tbody>
</tgroup>
@@ -917,7 +917,7 @@
<para>As noted in the comment, ecStep will not equal ecJob, they are two
different <classname>ExecutionContext</classname>s. The one scoped to the
<classname>Step</classname> will be saved at every commit point in the
<classname>Step</classname>, wheras the one scoped to the
<classname>Step</classname>, whereas the one scoped to the
<classname>Job</classname> will be saved in between every
<classname>Step</classname> execution.</para>
</section>
@@ -995,4 +995,4 @@
that it's not valid, returning null indicates that it should not be
written out.</para>
</section>
</chapter>
</chapter>

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -48,7 +48,7 @@
<para>The namespace defaults to referencing a repository with an id of
'jobRepository', which is a sensible default. However, this can be
overriden explicitely:</para>
overridden explicitly:</para>
<programlisting>
&lt;job id="footballJob" <emphasis role="bold">job-repository="specialRepository"</emphasis>&gt;
@@ -64,12 +64,13 @@
<para>One key concern when execution a batch job, is what happens when a
failed job is restarted? A Job is considered to have been 'restarted' if
the same JobInstance has more than one JobExecution. Ideally, all jobs
should be able to start up where they left off, but there are scenarios
where this is not possible. <emphasis role="bold">It is entirely up to
the developer to ensure that a new instance is always created in this
scenario</emphasis>. However, Spring Batch does provide some help. If a
Job should never be restarted, but should always be run as part of a new
the same <classname>JobInstance</classname> has more than one
JobExecution. Ideally, all jobs should be able to start up where they
left off, but there are scenarios where this is not possible. <emphasis
role="bold">It is entirely up to the developer to ensure that a new
instance is always created in this scenario</emphasis>. However, Spring
Batch does provide some help. If a Job should never be restarted, but
should always be run as part of a new
<classname>JobInstance</classname>, then the restartable property may be
set to 'false':</para>
@@ -196,7 +197,7 @@
<section>
<title>Configuring a JobRepository</title>
<para>As described in Chatper 2, the JobRepository is used for basic CRUD
<para>As described in Chapter 2, the JobRepository is used for basic CRUD
operations of the various persisted domain objects within Spring Batch,
such as JobExecution and StepExecution. It is required by many of the
major framework features, such as the <classname>JobLauncher</classname>,
@@ -236,7 +237,7 @@
to collide in this way. However, since a call to the
<classname>create*</classname> method is quite short, it is unlikely
that the SERIALIZED will cause problems, as long as the database
platform supports it. However, this can be overriden:</para>
platform supports it. However, this can be overridden:</para>
<para><programlisting>
&lt;job-repository id="jobRepository"
@@ -264,7 +265,7 @@
</programlisting></para>
<para>This fragment can be used as is, with almost no changes. Remember
also to include the appropiate namespace declarations and to make sure
also to include the appropriate namespace declarations and to make sure
spring-tx and spring-aop (or the whole of spring) is on the
classpath.</para>
@@ -274,11 +275,11 @@
<para>Spring Batch provides DDL samples for the meta-data tables in
the Core jar file for several common database platforms. Index
declarations are not included in that DDL because there are too many
variations in how users may want to index dependeing on their precise
variations in how users may want to index depending on their precise
platform, local conventions and also the business requirements of how
the jobs will be operated. The table below provides some indication as
to which columns are going to be used in a WHERE clause by the Dao
ipmlementations provided by Spring Batch, and how frequently they
implementations provided by Spring Batch, and how frequently they
might be used, so that individual projects can make up their own minds
about indexing.</para>
@@ -679,7 +680,7 @@
</imageobject>
</mediaobject>
<para>The JobExplorer and JobOperatoer interfaces, which will be discussed
<para>The JobExplorer and JobOperator interfaces, which will be discussed
below, add additional functionality for querying and controlling the meta
data.</para>
@@ -783,8 +784,8 @@
<classname>JobRepository</classname>,
<classname>JobExplorer</classname>, and
<classname>JobRegistry</classname>. For this reason, the provided
implementation of JobOperator, SimpleJobOperator, has many dependencies:
</para>
implementation of JobOperator, SimpleJobOperator, has many
dependencies:</para>
<programlisting>
&lt;bean id="jobOperator" class="org.springframework.batch.core.launch.support.SimpleJobOperator"&gt;
@@ -850,7 +851,7 @@
</programlisting>
<para>In this example, the value with a key of 'run.id' is used to
descriminate between JobInstances. If the JobParameters passed in is
discriminate between JobInstances. If the JobParameters passed in is
null, it can be assumed that the Job has never been run before and thus
it's initial state can be returned. However, if not, the old value is
obtained, incremented by one, and returned. An incrementer can be
@@ -889,4 +890,4 @@
for the <classname>JobExecution</classname> before finishing.</para>
</section>
</section>
</chapter>
</chapter>

View File

@@ -331,14 +331,14 @@
</programlisting></para>
<para>The basic constract is that, given the current line, and the
line number its associated with, return a resulting domain object.
This is similiar to <classname>RowMapper</classname> in that each line
is associated with it's line number, just as each row in a resultset
is tied to the row number it belongs to. This allows for tying the
line number to the resulting domain object for identitiy comparison,
or for more informative logging. However, unlike
<classname>RowMapper</classname>, the
<para>The basic contract is that, given the current line, and the line
number its associated with, return a resulting domain object. This is
similar to <classname>RowMapper</classname> in that each line is
associated with it's line number, just as each row in a
<classname>ResultSet</classname> is tied to the row number it belongs
to. This allows for tying the line number to the resulting domain
object for identity comparison, or for more informative logging.
However, unlike <classname>RowMapper</classname>, the
<classname>LineMapper</classname> is given a raw line which, as
discussed above, only gets you halfway there. What is needed is
tokenization of the line into a <classname>FieldSet</classname>, which
@@ -566,7 +566,7 @@
<para>There is one additional functionality a
<classname>LineTokenizer</classname> that is similar in function to a
JDBC <classname>ResultSet</classname>. The names of the fields can be
Jdbc <classname>ResultSet</classname>. The names of the fields can be
injected into the <classname>LineTokenizer</classname> to increase the
readability of the mapping function. First, the column names of all
fields in the flat file are injected into the
@@ -608,10 +608,10 @@
<para>For many, having to write a specific
<classname>FieldSetMapper</classname> is equally as cumbersome as
writing a specific <classname>RowMapper</classname> for a
JdbcTemplate. Spring Batch makes this easier by providing a
<classname>FieldSetMapper</classname> that automatically maps fields
by matching a field name with a setter on the object using the
JavaBean specification. Again using the football example, the
<classname>JdbcTemplate</classname>. Spring Batch makes this easier by
providing a <classname>FieldSetMapper</classname> that automatically
maps fields by matching a field name with a setter on the object using
the JavaBean specification. Again using the football example, the
<classname>FieldSetMapper</classname> configuration looks like the
following:</para>
@@ -641,7 +641,7 @@
<title>Fixed Length file formats</title>
<para>So far only delimited files have been discussed in much detail,
however, they respresent only half of the file reading picture. Many
however, they represent only half of the file reading picture. Many
organizations that use flat files use fixed length formats. An example
fixed length file is below:</para>
@@ -689,8 +689,8 @@
</programlisting>
<para>This <classname>LineTokenizer</classname> will return the same
<classname>FieldSet</classname> as if a dlimiter had been used,
allowing the same approachs above to be used such as the
<classname>FieldSet</classname> as if a delimiter had been used,
allowing the same approach above to be used such as the
<classname>BeanWrapperFieldSetMapper</classname>, in a way that is
ignorant of how the actual line was parsed.</para>
@@ -907,7 +907,7 @@
<section>
<title>PassThroughLineAggregator</title>
<para>The most basic implementation of the LineAggreagot interface
<para>The most basic implementation of the LineAggregator interface
is the PassThroughLineAggregator, which simply assumes that the
object is already a string, or that it's string representation is
acceptable for writing:</para>
@@ -1000,7 +1000,7 @@
</listitem>
</orderedlist></para>
<para>File writing has similiar, but inverse steps:</para>
<para>File writing has similar, but inverse steps:</para>
<orderedlist>
<listitem>
@@ -1145,9 +1145,9 @@
<title>Fixed Width File Writing Example</title>
<para>Delimited is not the only type of flat file format, many prefer
to use a set width for each column to deliniate between fields, which
to use a set width for each column to delineate between fields, which
is usually referred to as 'fixed width'. Spring Batch supports this in
file writting via the FormatterLineAggregator. Using the same
file writing via the FormatterLineAggregator. Using the same
CustomerCredit domain object described above, it can be configured as
follows:</para>
@@ -1248,7 +1248,7 @@
above. Everything between '&lt;trade&gt;' and '&lt;/trade&gt;' is
considered one 'fragment'. Spring Batch uses Object/XML Mapping (OXM) to
bind fragments to objects. However, Spring Batch is not tied to any
particular xml binding technology. Typical use is to delegate to <ulink
particular XML binding technology. Typical use is to delegate to <ulink
url="http://static.springframework.org/spring-ws/site/reference/html/oxm.html"><citetitle>Spring
OXM</citetitle></ulink>, which provides uniform abstraction for the most
popular OXM technologies. The dependency on Spring OXM is optional and you
@@ -1446,7 +1446,7 @@
optionally sets the overwriteOutput=true, mentioned earlier in the
chapter for specifying whether an existing file can be overwritten. It
should be noted the marshaller used for the writer is the exact same as
the one used in the reading example from ealier in the chapter:</para>
the one used in the reading example from earlier in the chapter:</para>
<programlisting>
&lt;bean id="customerCreditMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"&gt;
@@ -1592,7 +1592,7 @@
<section>
<title>JdbcCursorItemReader</title>
<para><classname>JdbcCursorItemReader</classname> is the JDBC
<para><classname>JdbcCursorItemReader</classname> is the Jdbc
implementation of the cursor based technique. It works directly with a
<classname>ResultSet</classname> and requires a SQL statement to run
against a connection obtained from a
@@ -1650,7 +1650,7 @@
<classname>DataSource</classname>, the provided SQL will be run
against it, and the <methodname>mapRow</methodname> method will be
called for each row in the <classname>ResultSet</classname>. Let's
constrast this with the approach of the
contrast this with the approach of the
<classname>JdbcCursorItemReader</classname>:</para>
<programlisting>
@@ -1717,7 +1717,7 @@
<row>
<entry>fetchSize</entry>
<entry>Gives the JDBC driver a hint as to the number of rows
<entry>Gives the Jdbc driver a hint as to the number of rows
that should be fetched from the database when more rows are
needed by the <classname>ResultSet</classname> object used
by the ItemReader. By default, no hint is given.</entry>
@@ -1768,10 +1768,10 @@
<row>
<entry>driverSupportsAbsolute</entry>
<entry>Defaults to false. Indicates whether the JDBC driver
<entry>Defaults to false. Indicates whether the Jdbc driver
supports setting the absolute row on a
<classname>ResultSet</classname>. It is recommended that
this is set to true for JDBC drivers that supports
this is set to true for Jdbc drivers that supports
ResultSet.absolute() as it may improve performance,
especially if a step fails while working with a large data
set.</entry>
@@ -1795,8 +1795,8 @@
'READ_ONLY' and 'HOLD_CUSORS_OVER_COMMIT' options. This
allows holding the cursor open over transaction start and
commits performed in the step processing. To use this
feature you need a database that supports this and a JDBC
driver supporting JDBC 3.0 or later.</entry>
feature you need a database that supports this and a Jdbc
driver supporting Jdbc 3.0 or later.</entry>
</row>
</tbody>
</tgroup>
@@ -1888,7 +1888,7 @@
<classname>JdbcPagingItemReader</classname> needs a
<classname>PagingQueryProvider</classname> responsible for providing
the SQL queries used to retrieve the rows making up a page. Since each
database has its own strategy for proviing paging support, we need to
database has its own strategy for providing paging support, we need to
use a different <classname>PagingQueryProvider</classname> for each
supported database type. There is also the
<classname>SimpleDelegatingPagingQueryProvider</classname> that will
@@ -1952,7 +1952,7 @@
<classname>ItemReader</classname> is the
<classname>JpaPagingItemReader</classname>. JPA doesn't have a concept
similar to the Hibernate <classname>StatelessSession</classname> so we
have to use other features provided by the JPA specification. SInce
have to use other features provided by the JPA specification. Since
JPA supports paging, this is a natural choice when it comes to using
JPA for batch processing. After each page is read the entities will
become detached and the persistence context will be cleared in order
@@ -2021,7 +2021,7 @@
<classname>IbatisPagingItemReader</classname> and there is also a
<classname>_page</classname> variable that can be used if necessary.
The syntax for the paging queries varies with the database used. Here
is an example for Oracle (unfortunatey we need to use CDATA for some
is an example for Oracle (unfortunately we need to use CDATA for some
operators since this belongs in an XML document):</para>
<programlisting> &lt;select id="getPagedCustomerCredits" resultMap="customerCreditResult"&gt;
@@ -2044,9 +2044,9 @@
for files because they must act as if they're transactional, keeping
track of written items and flushing or clearing at the appropriate
times. Databases have no need for this functionality, since the write is
already contained in a transaction. Users can create their own DAO's
that implement the <classname>ItemWriter</classname> interface or use
one from a custom <classname>ItemWriter</classname> that's written for
already contained in a transaction. Users can create their own DAOs that
implement the <classname>ItemWriter</classname> interface or use one
from a custom <classname>ItemWriter</classname> that's written for
generic processing concerns, either way, they should work without any
issues. One thing to look out for is the performance and error handling
capabilities that are provided by batching the outputs. This is most
@@ -2201,10 +2201,10 @@
}</programlisting>
<para>An <classname>ItemProcessor</classname> is very simple, given one
object, transorm it and return another. The object provided may or may not
be of the same type. The point is that business logic may be applied
object, transform it and return another. The object provided may or may
not be of the same type. The point is that business logic may be applied
within process, and is completely up to the developer to create. An
<classname>ItemProcessor</classname> can be wired direclty into a step,
<classname>ItemProcessor</classname> can be wired directly into a step,
For example, assuming an <classname>ItemReader</classname> provides a
class of type Foo, and it needs to be converted to type Bar before being
written out. An <classname>ItemTransformer</classname> can be written that
@@ -2346,7 +2346,7 @@
itemProcessors.add(new BarTransformer());
compositeProcessor.setItemProcessors(itemProcessors);</programlisting>
<para>Just as with the previous example, the compsite processor can be
<para>Just as with the previous example, the composite processor can be
configured into the <classname>Step</classname>:</para>
<programlisting>
@@ -2453,7 +2453,7 @@
flipped from false to true. The SQL statement can then contain an extra
statement in the where clause, such as: "where PROCESSED_IND = false",
thereby insuring that only unprocessed records will be returned in the
case of a restart. In this scenario, it is prefereable to not store any
case of a restart. In this scenario, it is preferable to not store any
state, such as the current row number, since it will be irrelevant upon
restart. For this reason, all readers and writers include the 'saveState'
property:</para>
@@ -2557,9 +2557,9 @@
actually valid in many scenarios, but it is sometimes preferable that
a batch job starts off at where it left off. The key discriminant is
often whether the reader is stateful or stateless. A stateless reader
does not need to worry about restartablility, but a stateful one has
to try and reconstitute its last known state on restart. For this
reason, we recommend that you keep custom readers stateless as far as
does not need to worry about restartability, but a stateful one has to
try and reconstitute its last known state on restart. For this reason,
we recommend that you keep custom readers stateless as far as
possible, so you don't have to worry about restartability.</para>
<para>If you do need to store state, then in Spring Batch, this is
@@ -2696,4 +2696,4 @@
</section>
</section>
</section>
</chapter>
</chapter>

View File

@@ -8,7 +8,7 @@
<title>RepeatTemplate</title>
<para>Batch processing is about repetitive actions - either as a simple
optimisation, or as part of a job. To strategise and generalise the
optimisation, or as part of a job. To strategie and generalise the
repetition, and provide what amounts to an iterator framework, Spring
Batch has the <classname>RepeatOperations</classname> interface. The
<classname>RepeatOperations</classname> interface looks like this:</para>
@@ -137,10 +137,10 @@ template.iterate(new RepeatCallback() {
flexible, so that they can be created with any code and description the
user needs. Spring Batch comes with some standard values out of the box,
to support common use cases, but users are free to create their own
values, as long as the semantics of teh <code>continuable</code>
values, as long as the semantics of the <code>continuable</code>
property are honoured.</para>
<para>ExitStatus values can also be combined with valrious operators
<para>ExitStatus values can also be combined with various operators
built into the class as methods. You can add an exit code, or
description, or combine the continuable values with logical AND using
methods in ExitStatus. You can also combine two ExitStatus values with
@@ -163,7 +163,7 @@ template.iterate(new RepeatCallback() {
the loop in the <methodname>iterate</methodname> method is determined by a
<classname>CompletionPolicy</classname> which is also a factory for the
<classname>ReapeatContext</classname>. The
<classname>RepeatTemplate</classname> has the reponsibility to use the
<classname>RepeatTemplate</classname> has the responsibility to use the
current policy to create a <classname>RepeatContext</classname> and pass
that in to the <classname>RepeatCallback</classname> at every stage in the
iteration. After a callback completes its
@@ -319,4 +319,4 @@ template.iterate(new RepeatCallback() {
<classname>ExceptionHandler</classname> in the provided
<classname>RepeatTemplate</classname>.</para>
</section>
</chapter>
</chapter>

View File

@@ -17,27 +17,27 @@
<classname>RetryOperations</classname> strategy. The
<classname>RetryOperations</classname> interface looks like this:</para>
<para><programlisting><![CDATA[public interface RetryOperations {
<para><programlisting>public interface RetryOperations {
<T> T execute(RetryCallback<T> retryCallback) throws Exception;
&lt;T&gt; T execute(RetryCallback&lt;T&gt; retryCallback) throws Exception;
<T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback)
&lt;T&gt; T execute(RetryCallback&lt;T&gt; retryCallback, RecoveryCallback&lt;T&gt; recoveryCallback)
throws Exception;
<T> T execute(RetryCallback<T> retryCallback, RetryState retryState)
&lt;T&gt; T execute(RetryCallback&lt;T&gt; retryCallback, RetryState retryState)
throws Exception, ExhaustedRetryException;
<T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback,
&lt;T&gt; T execute(RetryCallback&lt;T&gt; retryCallback, RecoveryCallback&lt;T&gt; recoveryCallback,
RetryState retryState) throws Exception;
}]]></programlisting>where the basic callback is a simple interface that
allows you to insert some business logic to be retried</para>
}</programlisting>where the basic callback is a simple interface that allows
you to insert some business logic to be retried</para>
<para><programlisting><![CDATA[public interface RetryCallback<T> {
<para><programlisting>public interface RetryCallback&lt;T&gt; {
T doWithRetry(RetryContext context) throws Throwable;
}]]></programlisting>The callback is executed and if it fails (by throwing an
}</programlisting>The callback is executed and if it fails (by throwing an
<classname>Exception</classname>), it will be retried until either it is
successful, or the implementation decides to abort. There are a number of
overloaded <methodname>execute</methodname> methods in the
@@ -50,18 +50,18 @@
<classname>RetryOperations</classname> is
<classname>RetryTemplate</classname>. It could be used like this</para>
<programlisting><![CDATA[RetryTemplate template = new RetryTemplate();
<programlisting>RetryTemplate template = new RetryTemplate();
template.setRetryPolicy(new TimeoutRetryPolicy(30000L));
Foo result = template.execute(new RetryCallback<Foo>() {
Foo result = template.execute(new RetryCallback&lt;Foo&gt;() {
public Foo doWithRetry(RetryContext context) {
// Do stuff that might fail, e.g. webservice operation
return result;
}
});]]></programlisting>
});</programlisting>
<para>In the example we execute a web service call and return the result
to the user. If that call fails then it is retried until a timeout is
@@ -90,17 +90,17 @@ Foo result = template.execute(new RetryCallback<Foo>() {
clients just pass in the callbacks together to the same method, for
example:</para>
<para><programlisting><![CDATA[Foo foo = template.execute(new RetryCallback<Foo>() {
<para><programlisting>Foo foo = template.execute(new RetryCallback&lt;Foo&gt;() {
public Foo doWithRetry(RetryContext context) {
// business logic here
},
new RecoveryCallback<Foo>() {
new RecoveryCallback&lt;Foo&gt;() {
Foo recover(RetryContext context) throws Exception {
// recover logic here
}
});]]></programlisting>If the business logic does not succeed before the
template decides to abort, then the client is given the chance to do
some alternate processing through the recovery callback.</para>
});</programlisting>If the business logic does not succeed before the template
decides to abort, then the client is given the chance to do some
alternate processing through the recovery callback.</para>
</section>
<section>
@@ -144,7 +144,7 @@ Foo result = template.execute(new RetryCallback<Foo>() {
<classname>RetryContextCache</classname> with a cluster cache of some
sort (even in a clustered environment this might be overkill).</para>
<para>Part of the reponsibility of the
<para>Part of the responsibility of the
<classname>RetryOperations</classname> is to recognise the failed
operations when they come back in a new execution (and usually wrapped
in a new transaction). To facilitate this, Spring Batch provides the
@@ -189,7 +189,7 @@ Foo result = template.execute(new RetryCallback<Foo>() {
or fail in the <methodname>execute</methodname> method is determined by a
<classname>RetryPolicy</classname> which is also a factory for the
<classname>RetryContext</classname>. The
<classname>RetryTemplate</classname> has the reponsibility to use the
<classname>RetryTemplate</classname> has the responsibility to use the
current policy to create a <classname>RetryContext</classname> and pass
that in to the <classname>RetryCallback</classname> at every attempt.
After a callback fails the <classname>RetryTemplate</classname> has to
@@ -210,8 +210,9 @@ Foo result = template.execute(new RetryCallback<Foo>() {
doesn't help to retry it. So don't retry on all exception types - try to
focus on only those exceptions that you expect to be retryable. It's not
usually harmful to the business logic to retry more aggressively, but
it's wasteful because if a failure is determinstic there could be a very
tight loop retrying something that you know in advance is fatal.</para>
it's wasteful because if a failure is deterministic there could be a
very tight loop retrying something that you know in advance is
fatal.</para>
</tip>
<para>Spring Batch provides some simple general purpose implementations of
@@ -226,7 +227,7 @@ Foo result = template.execute(new RetryCallback<Foo>() {
this list overrides the retryable list, so it can be used to give finer
control over the retry behaviour, e.g.</para>
<programlisting><![CDATA[SimpleRetryPolicy policy = new SimpleRetryPolicy(5);
<programlisting>SimpleRetryPolicy policy = new SimpleRetryPolicy(5);
// Retry on all exceptions (this is the default)
policy.setRetryableExceptions(new Class[] {Exception.class});
// ... but never retry IllegalStateException
@@ -235,11 +236,11 @@ policy.setFatalExceptions(new Class[] {ILlegalStateException.class});
// Use the policy...
RetryTemplate template = new RetryTemplate();
template.setRetryPolicy(policy);
template.execute(new RetryCallback<Foo>() {
template.execute(new RetryCallback&lt;Foo&gt;() {
public Foo doWithRetry(RetryContext context) {
// business logic here
}
});]]></programlisting>
});</programlisting>
<para>There is also a more flexible implementation called
<classname>ExceptionClassifierRetryPolicy</classname>, which allows the
@@ -265,20 +266,20 @@ template.execute(new RetryCallback<Foo>() {
<classname>RetryTemplate</classname> can pause execution according to the
<classname>BackoffPolicy</classname> in place.</para>
<para><programlisting><![CDATA[public interface BackoffPolicy {
<para><programlisting>public interface BackoffPolicy {
BackOffContext start(RetryContext context);
void backOff(BackOffContext backOffContext)
throws BackOffInterruptedException;
}]]></programlisting>A <classname>BackoffPolicy</classname> is free to
implement the backOff in any way it chooses. The policies provided by
Spring Batch out of the box all use <code>Object.wait()</code>. A common
use case is to backoff with an exponentially increasing wait period, to
avoid two retries getting into lock step and both failing - this is a
lesson learned from the ethernet. For this purpose Spring Batch provides
the <classname>ExponentialBackoffPolicy</classname>.</para>
}</programlisting>A <classname>BackoffPolicy</classname> is free to implement
the backOff in any way it chooses. The policies provided by Spring Batch
out of the box all use <code>Object.wait()</code>. A common use case is to
backoff with an exponentially increasing wait period, to avoid two retries
getting into lock step and both failing - this is a lesson learned from
the ethernet. For this purpose Spring Batch provides the
<classname>ExponentialBackoffPolicy</classname>.</para>
</section>
<section>
@@ -295,15 +296,15 @@ template.execute(new RetryCallback<Foo>() {
<para>The interface looks like this:</para>
<para><programlisting><![CDATA[public interface RetryListener {
<para><programlisting>public interface RetryListener {
void open(RetryContext context, RetryCallback<T> callback);
void open(RetryContext context, RetryCallback&lt;T&gt; callback);
void onError(RetryContext context, RetryCallback<T> callback, Throwable e);
void onError(RetryContext context, RetryCallback&lt;T&gt; callback, Throwable e);
void close(RetryContext context, RetryCallback<T> callback, Throwable e);
void close(RetryContext context, RetryCallback&lt;T&gt; callback, Throwable e);
}
]]></programlisting>The <methodname>open</methodname> and
</programlisting>The <methodname>open</methodname> and
<methodname>close</methodname> callbacks come before and after the entire
retry in the simplest case, and <methodname>onError</methodname> applies
to the individual RetryCallback calls. The <methodname>close</methodname>
@@ -334,20 +335,20 @@ template.execute(new RetryCallback<Foo>() {
<methodname>remoteCall</methodname> (for more detail on how to configure
AOP interceptors see the Spring User Guide):</para>
<programlisting><![CDATA[<aop:config>
<aop:pointcut id="transactional"
expression="execution(* com...*Service.remoteCall(..))" />
<aop:advisor pointcut-ref="transactional"
advice-ref="retryAdvice" order="-1"/>
</aop:config>
<programlisting>&lt;aop:config&gt;
&lt;aop:pointcut id="transactional"
expression="execution(* com...*Service.remoteCall(..))" /&gt;
&lt;aop:advisor pointcut-ref="transactional"
advice-ref="retryAdvice" order="-1"/&gt;
&lt;/aop:config&gt;
<bean id="retryAdvice"
class="org.springframework.batch.retry.interceptor.RetryOperationsInterceptor"/>
]]></programlisting>
&lt;bean id="retryAdvice"
class="org.springframework.batch.retry.interceptor.RetryOperationsInterceptor"/&gt;
</programlisting>
<para>The example above uses a default
<classname>RetryTemplate</classname> inside the interceptor. To change the
policies, listeners etc. you only need to inject an instance of
policies or listeners, you only need to inject an instance of
<classname>RetryTemplate</classname> into the interceptor.</para>
</section>
</chapter>
</chapter>

View File

@@ -510,7 +510,7 @@ INSERT INTO BATCH_JOB_SEQ values(0);</programlisting>
<section>
<title>Archiving</title>
<para>Because there are entries in multiple tables everytime a batch job
<para>Because there are entries in multiple tables every time a batch job
is run, it is common to create an archive strategy for the meta-data
tables. The tables themselves are designed to show a record of what
happened in the past, and generally won't affect the run of any job, with
@@ -538,4 +538,4 @@ INSERT INTO BATCH_JOB_SEQ values(0);</programlisting>
</listitem>
</itemizedlist>
</section>
</appendix>
</appendix>

View File

@@ -1257,12 +1257,12 @@
</programlisting>
<para>The above <classname>Resource</classname> will load the file from
the file system, at the location specificied. Note that absolute
locations have to start with a double slash ("//"). In most spring
applications, this solution is good enough because the names of these
are known at compile time. However, in batch scenarios, the file name
may need to be determined at runtime as a parameter to the job. This
could be solved using '-D' parameters, i.e. a system property:</para>
the file system, at the location specified. Note that absolute locations
have to start with a double slash ("//"). In most spring applications,
this solution is good enough because the names of these are known at
compile time. However, in batch scenarios, the file name may need to be
determined at runtime as a parameter to the job. This could be solved
using '-D' parameters, i.e. a system property:</para>
<programlisting>
&lt;bean id="flatFileItemReader"
@@ -1332,7 +1332,7 @@
order to use late binding, since the bean cannot actually be
instantiated until the <classname>Step</classname> starts, which
allows the attributes to be found. Because it is not part of the
Spring container by default, it must be added explicitly: </para>
Spring container by default, it must be added explicitly:</para>
<programlisting>
&lt;bean class="org.springframework.batch.core.scope.StepScope" /&gt;
@@ -1341,4 +1341,4 @@
</section>
</section>
</section>
</chapter>
</chapter>

View File

@@ -10,7 +10,7 @@
detail, so it won't be repeated here. It is important, however, to think
about how to 'end to end' test a batch job, which is what this chapter will
focus on. The spring-batch-test project includes classes that will help
factillitate this end-to-end test approach.</para>
facilitate this end-to-end test approach.</para>
<section>
<title>Creating a Unit Test Class</title>
@@ -27,7 +27,7 @@
<listitem>
<para><classname>@ContextConfiguration(locations = {...})</classname>:
Indicates which xml files contain the ApplicationContext.</para>
Indicates which XML files contain the ApplicationContext.</para>
</listitem>
</itemizedlist>
@@ -93,9 +93,9 @@
<section>
<title>Testing Individual Steps</title>
<para>For complex batch jobs, test cases in the end-to-end tesing approach
may become unmanageable. It these cases, it may be more useful to have
test cases to test individual steps on their own. The
<para>For complex batch jobs, test cases in the end-to-end testing
approach may become unmanageable. It these cases, it may be more useful to
have test cases to test individual steps on their own. The
<classname>AbstractJobTests</classname> class contains a method
<methodname>launchStep</methodname> that takes a step name and runs just
that particular <classname>Step</classname>. This approach allows for more