Spelling and grammar corrections to the docs.
This commit is contained in:
@@ -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><job></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 |
BIN
docs/src/site/docbook/reference/images/job-repository.png
Normal file
BIN
docs/src/site/docbook/reference/images/job-repository.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -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>
|
||||
<job id="footballJob" <emphasis role="bold">job-repository="specialRepository"</emphasis>>
|
||||
@@ -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>
|
||||
<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>
|
||||
<bean id="jobOperator" class="org.springframework.batch.core.launch.support.SimpleJobOperator">
|
||||
@@ -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>
|
||||
|
||||
@@ -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 '<trade>' and '</trade>' 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>
|
||||
<bean id="customerCreditMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
|
||||
@@ -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> <select id="getPagedCustomerCredits" resultMap="customerCreditResult">
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
<T> T execute(RetryCallback<T> retryCallback) throws Exception;
|
||||
|
||||
<T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback)
|
||||
<T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback)
|
||||
throws Exception;
|
||||
|
||||
<T> T execute(RetryCallback<T> retryCallback, RetryState retryState)
|
||||
<T> T execute(RetryCallback<T> retryCallback, RetryState retryState)
|
||||
throws Exception, ExhaustedRetryException;
|
||||
|
||||
<T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> recoveryCallback,
|
||||
<T> T execute(RetryCallback<T> retryCallback, RecoveryCallback<T> 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<T> {
|
||||
|
||||
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<Foo>() {
|
||||
|
||||
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<Foo>() {
|
||||
public Foo doWithRetry(RetryContext context) {
|
||||
// business logic here
|
||||
},
|
||||
new RecoveryCallback<Foo>() {
|
||||
new RecoveryCallback<Foo>() {
|
||||
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<Foo>() {
|
||||
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<T> callback);
|
||||
|
||||
void onError(RetryContext context, RetryCallback<T> callback, Throwable e);
|
||||
void onError(RetryContext context, RetryCallback<T> callback, Throwable e);
|
||||
|
||||
void close(RetryContext context, RetryCallback<T> callback, Throwable e);
|
||||
void close(RetryContext context, RetryCallback<T> 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><aop:config>
|
||||
<aop:pointcut id="transactional"
|
||||
expression="execution(* com...*Service.remoteCall(..))" />
|
||||
<aop:advisor pointcut-ref="transactional"
|
||||
advice-ref="retryAdvice" order="-1"/>
|
||||
</aop:config>
|
||||
|
||||
<bean id="retryAdvice"
|
||||
class="org.springframework.batch.retry.interceptor.RetryOperationsInterceptor"/>
|
||||
]]></programlisting>
|
||||
<bean id="retryAdvice"
|
||||
class="org.springframework.batch.retry.interceptor.RetryOperationsInterceptor"/>
|
||||
</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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
<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>
|
||||
<bean class="org.springframework.batch.core.scope.StepScope" />
|
||||
@@ -1341,4 +1341,4 @@
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
||||
</chapter>
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user