BATCH-1056: fixed errors
This commit is contained in:
@@ -10,15 +10,13 @@
|
||||
<table>
|
||||
<title>Available Item Readers</title>
|
||||
|
||||
<tgroup cols="3">
|
||||
<tgroup cols="2">
|
||||
<colspec align="center" />
|
||||
|
||||
<thead>
|
||||
<row>
|
||||
<entry align="center">Item Reader</entry>
|
||||
|
||||
<entry align="center">Type of Item Provided</entry>
|
||||
|
||||
<entry align="center">Description</entry>
|
||||
</row>
|
||||
</thead>
|
||||
@@ -28,8 +26,6 @@
|
||||
<entry
|
||||
align="left">AbstractItemCountingItemStreamItemReader</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left">Abstract base class that provides basic
|
||||
restart capabilities by counting the number of items returned from
|
||||
an <classname>ItemReader</classname>.</entry>
|
||||
@@ -38,8 +34,6 @@
|
||||
<row>
|
||||
<entry align="left">ListItemReader</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left">Provides the items from a list, one at a
|
||||
time</entry>
|
||||
</row>
|
||||
@@ -47,8 +41,6 @@
|
||||
<row>
|
||||
<entry align="left">ItemReaderAdapter</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left">Adapts any class to the
|
||||
<classname>ItemReader</classname> interface.</entry>
|
||||
</row>
|
||||
@@ -56,8 +48,6 @@
|
||||
<row>
|
||||
<entry align="left">AggregateItemReader</entry>
|
||||
|
||||
<entry align="left">java.util.Collection</entry>
|
||||
|
||||
<entry align="left">An ItemReader that delivers a list as its
|
||||
item, storing up objects from the injected ItemReader until they
|
||||
are ready to be packed out as a collection. This ItemReader should
|
||||
@@ -71,9 +61,7 @@
|
||||
<row>
|
||||
<entry align="left">FlatFileItemReader</entry>
|
||||
|
||||
<entry align="left">java.lang.String</entry>
|
||||
|
||||
<entry align="left">Reads from a flat file, includes ItemStream
|
||||
<entry align="left">Reads from a flat file. Includes ItemStream
|
||||
and Skippable functionality. See section on Read from a
|
||||
File</entry>
|
||||
</row>
|
||||
@@ -81,8 +69,6 @@
|
||||
<row>
|
||||
<entry align="left">StaxEventItemReader</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left">Reads via StAX. See HOWTO - Read from a
|
||||
File</entry>
|
||||
</row>
|
||||
@@ -90,45 +76,28 @@
|
||||
<row>
|
||||
<entry align="left">JdbcCursorItemReader</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left">Reads from a database cursor via JDBC. See
|
||||
HOWTO - Read from a Database</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry align="left">DrivingQueryItemReader</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left">Base class for operations that read from a
|
||||
database based on a single driving query. Configured by injecting
|
||||
a KeyGenerator object. See HOWTO - Read from a Database</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry align="left">HibernateCursorItemReader</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left">Reads from a cursor based on an HQL query. See
|
||||
section on Reading from a Database</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry align="left">IbatisDrivingQueryItemReader</entry>
|
||||
<entry align="left">IbatisPagingItemReader</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left">Reads via iBATIS based on a driving query. See
|
||||
HOWTO - Read from a Database</entry>
|
||||
<entry align="left">Reads via iBATIS based on a query. Pages
|
||||
through the rows so that large datasets can be read without
|
||||
running out of memory. See HOWTO - Read from a Database</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry align="left">JmsItemReader</entry>
|
||||
|
||||
<entry align="left">javax.jms.Message</entry>
|
||||
|
||||
<entry align="left">Given a Spring JmsOperations object and a JMS
|
||||
Destination or destination name to send errors, provides items
|
||||
received through the injected JmsOperations receive()
|
||||
@@ -138,8 +107,6 @@
|
||||
<row>
|
||||
<entry align="left">JpaPagingItemReader</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left">Given a JPQL statement, pages through the
|
||||
rows, such that large datasets can be read without running out of
|
||||
memory</entry>
|
||||
@@ -148,8 +115,6 @@
|
||||
<row>
|
||||
<entry align="left">JdbcPagingItemReader</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left">Given a SQL statement, pages through the rows,
|
||||
such that large datasets can be read without running out of
|
||||
memory</entry>
|
||||
@@ -165,15 +130,13 @@
|
||||
<table>
|
||||
<title>Available Item Writers</title>
|
||||
|
||||
<tgroup cols="3">
|
||||
<tgroup cols="2">
|
||||
<colspec align="center" />
|
||||
|
||||
<thead>
|
||||
<row>
|
||||
<entry align="center">Item Writer</entry>
|
||||
|
||||
<entry align="center">Type of Item Written</entry>
|
||||
|
||||
<entry align="center">Description</entry>
|
||||
</row>
|
||||
</thead>
|
||||
@@ -182,29 +145,14 @@
|
||||
<row>
|
||||
<entry align="left">AbstractItemStreamItemWriter</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left">Abstract base class that combines the
|
||||
<classname>ItemStream</classname> and
|
||||
<classname>ItemWriter</classname> interfaces.</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry align="left">BatchSqlUpdateItemWriter</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left"><classname>ItemWriter</classname> that uses
|
||||
batching freatures from a <classname>PreparedStatement</classname>
|
||||
if available and can take rudimentary steps to locate a failure
|
||||
during a <methodname>flush</methodname>.</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry align="left">CompositeItemWriter</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left">Passes an item to the process method of each
|
||||
in an injected <emphasis role="bold">List</emphasis> of <emphasis
|
||||
role="bold">ItemWriter</emphasis> objects</entry>
|
||||
@@ -213,8 +161,6 @@
|
||||
<row>
|
||||
<entry align="left">ItemWriterAdapter</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left">Adapts any class to the
|
||||
<classname>ItemWriter</classname> interface.</entry>
|
||||
</row>
|
||||
@@ -222,8 +168,6 @@
|
||||
<row>
|
||||
<entry align="left">PropertyExtractingDelegatingItemWriter</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left">Extends AbstractMethodInvokingDelegator
|
||||
creating arguments on the fly. Arguments are created by retrieving
|
||||
the values from the fields in the item to be processed (via a
|
||||
@@ -234,19 +178,12 @@
|
||||
<row>
|
||||
<entry align="left">FlatFileItemWriter</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
|
||||
<entry align="left">Attempts to convert the item to a <emphasis
|
||||
role="bold">String</emphasis>, <emphasis
|
||||
role="bold">Collection</emphasis> or array using an injected
|
||||
<emphasis role="bold">Coverter</emphasis> and then
|
||||
recurses.</entry>
|
||||
<entry align="left">Writes to a flat file. Includes ItemStream and
|
||||
Skippable functionality. See section on Writing to a File</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry align="left">HibernateAwareItemWriter</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
<entry align="left">HibernateItemWriter</entry>
|
||||
|
||||
<entry align="left">This item writer is hibernate session aware
|
||||
and handles some transaction-related work that a non-"hibernate
|
||||
@@ -255,9 +192,16 @@
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry align="left">JpaAwareItemWriter</entry>
|
||||
<entry align="left">JdbcBatchItemWriter</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
<entry align="left">Uses batching freatures from a
|
||||
<classname>PreparedStatement</classname>, if available, and can
|
||||
take rudimentary steps to locate a failure during a
|
||||
<methodname>flush</methodname>.</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry align="left">JpaItemWriter</entry>
|
||||
|
||||
<entry align="left">This item writer is JPA EntityManager aware
|
||||
and handles some transaction-related work that a non-"jpa aware"
|
||||
@@ -266,9 +210,7 @@
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry align="left">StaxEventWriterItemWriter</entry>
|
||||
|
||||
<entry align="left">java.lang.Object</entry>
|
||||
<entry align="left">StaxEventItemWriter</entry>
|
||||
|
||||
<entry align="left">Uses an <emphasis
|
||||
role="bold">ObjectToXmlSerializer</emphasis> implementation to
|
||||
|
||||
@@ -5,29 +5,31 @@
|
||||
<title>Common Batch Patterns</title>
|
||||
|
||||
<para>Some batch jobs can be assembled purely from off-the-shelf components
|
||||
in Spring Batch, mostly the <classname>ItemReader</classname> and
|
||||
<classname>ItemWriter</classname> implementations. Where this is not
|
||||
possible (the majority of cases) the main API entry points for application
|
||||
in Spring Batch. For instance the <classname>ItemReader</classname> and
|
||||
<classname>ItemWriter</classname> implementations can be configured to cover
|
||||
a wide range of scenarios. However, for the majority of cases, custom code
|
||||
will have to be written. The main API entry points for application
|
||||
developers are the <classname>Tasklet</classname>,
|
||||
<classname>ItemReader</classname>, <classname>ItemWriter</classname> and the
|
||||
various listener interfaces. Most simple batch jobs will be able to use
|
||||
off-the-shelf input from a Spring Batch <classname>ItemReader</classname>,
|
||||
but it is very often the case that there are custom concerns in the
|
||||
processing and writing, which normally leads developers to implement an
|
||||
<classname>ItemWriter</classname>, or
|
||||
<classname>ItemTransformer</classname>.</para>
|
||||
but it is often the case that there are custom concerns in the processing
|
||||
and writing, which require developers to implement an
|
||||
<classname>ItemWriter</classname> or
|
||||
<classname>ItemProcessor</classname>.</para>
|
||||
|
||||
<para>Here we provide a few examples of common patterns in custom business
|
||||
logic, mainly using the listener interfaces . It should be noted that an
|
||||
<classname>ItemReader</classname> or <classname>ItemWriter</classname> can
|
||||
implement the listener interfaces as well if appropriate.</para>
|
||||
<para>Here, we provide a few examples of common patterns in custom business
|
||||
logic. These examples primarily feature the listener interfaces. It should
|
||||
be noted that an <classname>ItemReader</classname> or
|
||||
<classname>ItemWriter</classname> can implement a listener interface as
|
||||
well, if appropriate.</para>
|
||||
|
||||
<section>
|
||||
<title>Logging Item Processing and Failures</title>
|
||||
|
||||
<para>A common use case is the need for special handling of errors in a
|
||||
step, item by item, perhaps logging to a special channel, or inserting a
|
||||
record into a database. The <classname>StepHandlerStep</classname>
|
||||
record into a database. A chunk-oriented <classname>Step</classname>
|
||||
(created from the step factory beans) allows users to implement this use
|
||||
case with a simple <classname>ItemReadListener</classname>, for errors on
|
||||
read, and an <classname>ItemWriteListener</classname>, for errors on
|
||||
@@ -71,14 +73,16 @@
|
||||
<section>
|
||||
<title>Stopping a Job Manually for Business Reasons</title>
|
||||
|
||||
<para>Spring Batch provides a stop() method through the JobLauncher
|
||||
interface, but this is really aimed at the operator, rather than the
|
||||
application programmer. Sometimes it is more convenient or makes more
|
||||
sense to stop a job execution from within the business logic.</para>
|
||||
<para>Spring Batch provides a <methodname>stop</methodname>() method
|
||||
through the <classname>JobLauncher</classname> interface, but this is
|
||||
really for use by the operator rather than the application programmer.
|
||||
Sometimes it is more convenient or makes more sense to stop a job
|
||||
execution from within the business logic.</para>
|
||||
|
||||
<para>The simplest thing to do is to throw a RuntimeException (one that
|
||||
isn't retried indefinitely or skipped), For example, a custom exception
|
||||
type could be used, as in the example below:</para>
|
||||
<para>The simplest thing to do is to throw a
|
||||
<classname>RuntimeException</classname> (one that isn't retried
|
||||
indefinitely or skipped). For example, a custom exception type could be
|
||||
used, as in the example below:</para>
|
||||
|
||||
<programlisting>public class PoisonPillItemWriter implements ItemWriter<T> {
|
||||
|
||||
@@ -95,15 +99,15 @@
|
||||
<para>Another simple way to stop a step from executing is to simply return
|
||||
<code>null</code> from the <classname>ItemReader</classname>:</para>
|
||||
|
||||
<programlisting>public class EarlyCompletionItemReader extends AbstractItemReader {
|
||||
<programlisting>public class EarlyCompletionItemReader implements ItemReader<T> {
|
||||
|
||||
private ItemReader delegate;
|
||||
private ItemReader<T> delegate;
|
||||
|
||||
public void setDelegate(ItemReader delegate) { ... }
|
||||
public void setDelegate(ItemReader<T> delegate) { ... }
|
||||
|
||||
public Object read() throws Exception {
|
||||
public T read() throws Exception {
|
||||
|
||||
Object item = delegate.read();
|
||||
T item = delegate.read();
|
||||
|
||||
if (isEndItem(item)) {
|
||||
return null; // end the step here
|
||||
@@ -138,9 +142,10 @@
|
||||
<classname>StepExecution</classname>, which is checked by the
|
||||
<classname>Step</classname> implementations in the framework in between
|
||||
item processing. To implement this alternative, we need access to the
|
||||
current StepExecution, and this can be achieved by implementing a
|
||||
StepListener and registering it with the Step. Here is an example of a
|
||||
listener that sets the flag:</para>
|
||||
current <classname>StepExecution</classname>, and this can be achieved by
|
||||
implementing a <classname>StepListener</classname> and registering it with
|
||||
the <classname>Step</classname>. Here is an example of a listener that
|
||||
sets the flag:</para>
|
||||
|
||||
<programlisting>public class CustomItemWriter extends ItemListenerSupport implements StepListener {
|
||||
|
||||
@@ -160,7 +165,7 @@
|
||||
|
||||
}</programlisting>
|
||||
|
||||
<para>The default behaviour here when the flag is set is for the step to
|
||||
<para>The default behavior here when the flag is set is for the step to
|
||||
throw a <classname>JobInterruptedException</classname>. This can be
|
||||
controlled through the <classname>StepInterruptionPolicy</classname>, but
|
||||
the only choice is to throw or not throw an exception, so this is always
|
||||
@@ -172,7 +177,7 @@
|
||||
|
||||
<para>A very common requirement is to aggregate information during the
|
||||
output process and to append a record at the end of a file summarizing the
|
||||
data, or providing a checksum. This can also be achieved with a callbacks
|
||||
data, or providing a checksum. This can also be achieved with a callback
|
||||
in the step, normally as part of a custom
|
||||
<classname>ItemWriter</classname>. In this case, since a job is
|
||||
accumulating state that should not be lost if the job aborts, the
|
||||
@@ -206,10 +211,8 @@
|
||||
}
|
||||
|
||||
public void write(Trade item) {
|
||||
|
||||
delegate.write(item);
|
||||
totalAmount += item.getAmount();
|
||||
|
||||
}
|
||||
|
||||
}</programlisting>
|
||||
@@ -220,8 +223,9 @@
|
||||
<classname>ExecutionContext</classname>. In this way we can be sure that
|
||||
when the <code>open()</code> callback is received on a restart. The
|
||||
framework garuntees we always get the last value that was committed. It
|
||||
should be noted that it is not always necessary to implement ItemStream.
|
||||
For example, if the ItemWriter is re-runnable, in the sense that it
|
||||
should be noted that it is not always necessary to implement
|
||||
<classname>ItemStream</classname>. For example, if the
|
||||
<classname>ItemWriter</classname> is re-runnable, in the sense that it
|
||||
maintains its own state in a transactional resource like a database, there
|
||||
is no need to maintain state within the writer itself.</para>
|
||||
</section>
|
||||
@@ -272,11 +276,9 @@
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
<para>As you can see, an existing DAO can be used to obtain a full 'Foo'
|
||||
object using the key obtained from the driving query. In Spring Batch,
|
||||
driving query style input is implemented with a
|
||||
<classname>DrivingQueryItemReader</classname>, which has only one
|
||||
dependency: a <classname>KeyCollector</classname></para>
|
||||
<para>An ItemProcessor should be used to transform the key obtained from
|
||||
the driving query into a full 'Foo' object. An existing DAO can be used to
|
||||
query for the full object based on the key.</para>
|
||||
</section>
|
||||
|
||||
<section id="multiLineRecords">
|
||||
|
||||
@@ -389,7 +389,7 @@
|
||||
will be kicked off again for 01-01, starting where it left off and
|
||||
completing successfully at 9:30. Because it's now the next day, the
|
||||
01-02 job must be run as well, which is kicked off just afterwards at
|
||||
9:31, and completes in it's normal one hour time at 10:30. There is no
|
||||
9:31, and completes in its normal one hour time at 10:30. There is no
|
||||
requirement that one <classname>JobInstance</classname> be kicked off
|
||||
after another, unless there is potential for the two jobs to attempt to
|
||||
access the same data, causing issues with locking at the database level.
|
||||
@@ -573,7 +573,7 @@
|
||||
<classname>JobExecution</classname>. However, if a step fails to execute
|
||||
because the step before it fails, there will be no execution persisted
|
||||
for it. A <classname>StepExecution</classname> will only be created when
|
||||
it's <classname>Step</classname> is actually started.</para>
|
||||
its <classname>Step</classname> is actually started.</para>
|
||||
|
||||
<para>Step executions are represented by objects of the
|
||||
<classname>StepExecution</classname> class. Each execution contains a
|
||||
|
||||
@@ -99,8 +99,8 @@
|
||||
|
||||
<glossdef>
|
||||
<para>An item represents the smallest ammount of complete data for
|
||||
processing. In the most simple terms this might mean a line in a file,
|
||||
a row in a database table, or a particular element in an XML
|
||||
processing. In the simplest terms, this might mean a line in a file, a
|
||||
row in a database table, or a particular element in an XML
|
||||
file.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
@@ -119,7 +119,7 @@
|
||||
<glossterm>Commit Interval</glossterm>
|
||||
|
||||
<glossdef>
|
||||
<para>A set of LUWs constitute a commit interval.</para>
|
||||
<para>A set of LUWs processed within a single transaction.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
<glossterm>Restartable</glossterm>
|
||||
|
||||
<glossdef>
|
||||
<para>- a job that can be executed again and will assume the same
|
||||
<para>A job that can be executed again and will assume the same
|
||||
identity as when run initially. In othewords, it is has the same job
|
||||
instance id.</para>
|
||||
</glossdef>
|
||||
@@ -157,14 +157,14 @@
|
||||
<glossterm>Rerunnable</glossterm>
|
||||
|
||||
<glossdef>
|
||||
<para>a job that is restartable and manages it's own state in terms of
|
||||
<para>A job that is restartable and manages its own state in terms of
|
||||
previous run's record processing. An example of a rerunnable step is
|
||||
one based on a driving query. If the driving query can be formed so
|
||||
that it will limit the processed rows when the job is restarted than
|
||||
it is re-runnable. This is managed by the application logic. Often
|
||||
times a condition is added to the where statement to limit the rows
|
||||
returned by the driving query with something like "and processedFlag
|
||||
!= true". </para>
|
||||
!= true".</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
|
||||
@@ -189,9 +189,8 @@
|
||||
calling a block of code, retry is stateful, and continually calls the
|
||||
same block of code with the same input, until it either succeeds, or
|
||||
some type of retry limit has been exceeded. It is only generally
|
||||
useful if the operation is non-deterministic meaning that a retry on a
|
||||
subsequent invocation might succeed because something in the
|
||||
environment has improved.</para>
|
||||
useful if a subsequent invocation of the operation might succeed
|
||||
because something in the environment has improved.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
|
||||
@@ -214,4 +213,4 @@
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
</glossdiv>
|
||||
</glossary>
|
||||
</glossary>
|
||||
|
||||
@@ -20,20 +20,21 @@
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
<para>While the Job object may seem like a simple container for steps, there
|
||||
are many configuration options that developers should be aware of.
|
||||
Furthermore, there are many considerations for how a
|
||||
<classname>Job</classname> will be run and how its meta data will be stored
|
||||
during that run. This chapter will explain the various configuration options
|
||||
and runtime concerns of a <classname>Job</classname>.</para>
|
||||
<para>While the <classname>Job</classname> object may seem like a simple
|
||||
container for steps, there are many configuration options of which a
|
||||
developers must be aware . Furthermore, there are many considerations for
|
||||
how a <classname>Job</classname> will be run and how its meta-data will be
|
||||
stored during that run. This chapter will explain the various configuration
|
||||
options and runtime concerns of a <classname>Job</classname>.</para>
|
||||
|
||||
<section>
|
||||
<title>Configuring a Job</title>
|
||||
|
||||
<para>There are multiple implementations of the <link
|
||||
linkend="job">Job</link> interface, however, the namespace abstracts away
|
||||
the differences in configuration. It has only three required dependencies:
|
||||
a name, <classname>JobRepository</classname>, and a list of Steps.</para>
|
||||
linkend="job"><classname>Job</classname></link> interface, however, the
|
||||
namespace abstracts away the differences in configuration. It has only
|
||||
three required dependencies: a name, <classname>JobRepository</classname>,
|
||||
and a list of <classname>Step</classname>s.</para>
|
||||
|
||||
<programlisting>
|
||||
<job id="footballJob">
|
||||
@@ -57,20 +58,26 @@
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>Note that if the job repository's default id is overridden, it must
|
||||
be explicitly specified on <emphasis role="bold">every</emphasis>
|
||||
<classname>Step</classname> <emphasis role="bold">as well as</emphasis> on
|
||||
the <classname>Job</classname>.</para>
|
||||
|
||||
<section>
|
||||
<title>Restartability</title>
|
||||
|
||||
<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 <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>
|
||||
<para>One key issue when execution a batch job concerns the behavior of
|
||||
a <classname>Job</classname> when it is restarted? The launching of a
|
||||
<classname>Job</classname> is considered to be a 'restart' if a
|
||||
<classname>JobExecution</classname> already exists for the particular
|
||||
<classname>JobInstance</classname>. 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 JobInstance is created in this scenario</emphasis>.
|
||||
However, Spring Batch does provide some help. If a
|
||||
<classname>Job</classname> 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>
|
||||
|
||||
<programlisting>
|
||||
<job id="footballJob" <emphasis role="bold">restartable="false"</emphasis>>
|
||||
@@ -131,8 +138,9 @@
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>Listeners can be added to a <classname>SimpleJob</classname> via
|
||||
the setJobListeners property:</para>
|
||||
<para><classname>JobListener</classname>s can be added to a
|
||||
<classname>SimpleJob</classname> via the listeners element on the
|
||||
job:</para>
|
||||
|
||||
<programlisting>
|
||||
<job id="footballJob">
|
||||
@@ -146,17 +154,17 @@
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>It should be noted that afterJob will be called regardless of the
|
||||
success or failure of the <classname>Job</classname>. If success or
|
||||
failure needs to be determined it can be obtained from the
|
||||
<classname>JobExecution</classname>:</para>
|
||||
<para>It should be noted that <methodname>afterJob</methodname> will be
|
||||
called regardless of the success or failure of the
|
||||
<classname>Job</classname>. If success or failure needs to be determined
|
||||
it can be obtained from the <classname>JobExecution</classname>:</para>
|
||||
|
||||
<programlisting>
|
||||
void afterJob(JobExecution jobExecution){
|
||||
if( jobExecution.getStatus = BatchStatus.COMPLETED ){
|
||||
if( jobExecution.getStatus() == BatchStatus.COMPLETED ){
|
||||
//job success
|
||||
}
|
||||
else if(jobExecution.getStatus = BatchStatus.FAILED){
|
||||
else if(jobExecution.getStatus() == BatchStatus.FAILED){
|
||||
//job failure
|
||||
}
|
||||
}
|
||||
@@ -168,14 +176,14 @@
|
||||
<title>JobFactory and Stateful Components in Steps</title>
|
||||
|
||||
<para>Unlike many traditional Spring applications, many of the
|
||||
components of a batch application are stateful, the file readers and
|
||||
components of a batch application are stateful; the file readers and
|
||||
writers are obvious examples. The recommended way to deal with this is
|
||||
to create a fresh <classname>ApplicationContext</classname> for each job
|
||||
execution. If the <classname>Job</classname> is launched from the
|
||||
command line with <classname>CommandLineJobRunner</classname> this is
|
||||
trivial. For more complex launching scenarios, where jobs are executed
|
||||
in parallel or serially from the same process, some extra steps have to
|
||||
be taken to ensure that the <classname>ApplicationContext</classname> is
|
||||
command line with <classname>CommandLineJobRunner</classname>, this is
|
||||
trivial. For more complex launching scenarios where jobs are executed in
|
||||
parallel or serially from the same process, some extra steps have to be
|
||||
taken to ensure that the <classname>ApplicationContext</classname> is
|
||||
refreshed. This is preferable to using prototype scope for the stateful
|
||||
beans because then they would not receive lifecycle callbacks from the
|
||||
container at the end of use. (e.g. through destroy-method in XML)</para>
|
||||
@@ -196,12 +204,13 @@
|
||||
<title>Configuring a JobRepository</title>
|
||||
|
||||
<para>As described in earlier, the <link
|
||||
linkend="jobRepository">JobRepository</link> 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>,
|
||||
linkend="jobRepository"><classname>JobRepository</classname></link> is
|
||||
used for basic CRUD operations of the various persisted domain objects
|
||||
within Spring Batch, such as <classname>JobExecution</classname> and
|
||||
<classname>StepExecution</classname>. It is required by many of the major
|
||||
framework features, such as the <classname>JobLauncher</classname>,
|
||||
<classname>Job</classname>, and <classname>Step</classname>. The batch
|
||||
namespace abstract much of the implementation details of the
|
||||
namespace abstracts away many of the implementation details of the
|
||||
<classname>JobRepository</classname> implementations and their
|
||||
collaborators. However, there are still a few configuration options
|
||||
available:</para>
|
||||
@@ -226,7 +235,7 @@
|
||||
<para>If the namespace is used, transactional advice will be
|
||||
automatically created around the repository. This is to ensure that the
|
||||
batch meta data, including state that is necessary for restarts after a
|
||||
failure, is persisted correctly. The behaviour of the framework is not
|
||||
failure, is persisted correctly. The behavior of the framework is not
|
||||
well defined if the repository methods are not transactional. The
|
||||
isolation level in the <code>create*</code> method attributes is
|
||||
specified separately to ensure that when jobs are launched, if two
|
||||
@@ -246,7 +255,7 @@
|
||||
</programlisting></para>
|
||||
|
||||
<para>If the namespace or factory beans aren't used then it is also
|
||||
essential to configure the transactional behaviour of the repository
|
||||
essential to configure the transactional behavior of the repository
|
||||
using AOP:</para>
|
||||
|
||||
<para><programlisting>
|
||||
@@ -266,7 +275,7 @@
|
||||
|
||||
<para>This fragment can be used as is, with almost no changes. Remember
|
||||
also to include the appropriate namespace declarations and to make sure
|
||||
spring-tx and spring-aop (or the whole of spring) is on the
|
||||
spring-tx and spring-aop (or the whole of spring) are on the
|
||||
classpath.</para>
|
||||
</section>
|
||||
|
||||
@@ -294,7 +303,7 @@
|
||||
as SYSTEM.TEST_JOB_EXECUTION.</para>
|
||||
|
||||
<note>
|
||||
<para>Only the table prefix is configurable, the table and column
|
||||
<para>Only the table prefix is configurable. The table and column
|
||||
names are not.</para>
|
||||
</note>
|
||||
</section>
|
||||
@@ -303,10 +312,11 @@
|
||||
<title>In-Memory Repository</title>
|
||||
|
||||
<para>There are scenarios in which you may not want to persist your
|
||||
domain objects to the database. One reason may be speed, storing domain
|
||||
domain objects to the database. One reason may be speed; storing domain
|
||||
objects at each commit point takes extra time. Another reason may be
|
||||
that you just don't need to persist status for a particular job. Spring
|
||||
batch provides a solution:</para>
|
||||
that you just don't need to persist status for a particular job. For
|
||||
this reason, Spring batch provides an in-memory Map version of the job
|
||||
respository:</para>
|
||||
|
||||
<programlisting> <bean id="jobRepository"
|
||||
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean" /></programlisting>
|
||||
@@ -318,7 +328,7 @@
|
||||
|
||||
<para>The most basic implementation of the
|
||||
<classname>JobLauncher</classname> interface is the
|
||||
<classname>SimpleJobLauncher</classname>. It's only required dependency is
|
||||
<classname>SimpleJobLauncher</classname>. Its only required dependency is
|
||||
a <classname>JobRepository</classname>, in order to obtain an
|
||||
execution:</para>
|
||||
|
||||
@@ -327,10 +337,11 @@
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
</bean></programlisting>
|
||||
|
||||
<para>Once a <link linkend="jobExecution">JobExecution</link> is obtained,
|
||||
it is passed to the execute method of <classname>Job</classname>,
|
||||
ultimately returning the <classname>JobExecution</classname> to the
|
||||
caller:</para>
|
||||
<para>Once a <link
|
||||
linkend="jobExecution"><classname>JobExecution</classname></link> is
|
||||
obtained, it is passed to the execute method of
|
||||
<classname>Job</classname>, ultimately returning the
|
||||
<classname>JobExecution</classname> to the caller:</para>
|
||||
|
||||
<mediaobject>
|
||||
<imageobject role="html">
|
||||
@@ -346,13 +357,13 @@
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
<para>The sequence is straightforward, and works well when launched from a
|
||||
scheduler, but causes issues when trying to launch from an HTTP request.
|
||||
In this scenario, the launching needs to be done asynchronously, so that
|
||||
the <classname>SimpleJobLauncher</classname> returns immediately to it's
|
||||
caller. This is because it is not good practice to keep an HTTP request
|
||||
open for the amount of time needed by long running processes such as
|
||||
batch. An example sequence is below:</para>
|
||||
<para>The sequence is straightforward and works well when launched from a
|
||||
scheduler. However, issues arise when trying to launch from an HTTP
|
||||
request. In this scenario, the launching needs to be done asynchronously
|
||||
so that the <classname>SimpleJobLauncher</classname> returns immediately
|
||||
to its caller. This is because it is not good practice to keep an HTTP
|
||||
request open for the amount of time needed by long running processes such
|
||||
as batch. An example sequence is below:</para>
|
||||
|
||||
<mediaobject>
|
||||
<imageobject role="html">
|
||||
@@ -388,16 +399,16 @@
|
||||
<section>
|
||||
<title>Running a Job</title>
|
||||
|
||||
<para>At a minimum, launching a batch job requires two things: the Job to
|
||||
be launched and a <classname>JobLauncher</classname>. Both can be
|
||||
contained within the same context or different contexts. For example, if
|
||||
launching a job from the command line, a new JVM will be instantiated for
|
||||
each Job, and thus every job will have it's own
|
||||
<classname>JobLauncher</classname>. However, if running from within a web
|
||||
container within the scope of an <classname>HttpRequest</classname>, there
|
||||
will usually be one <classname>JobLauncher</classname>, configured for
|
||||
asynchronous job launching, that multiple requests will invoke to launch
|
||||
their jobs.</para>
|
||||
<para>At a minimum, launching a batch job requires two things: the
|
||||
<classname>Job</classname> to be launched and a
|
||||
<classname>JobLauncher</classname>. Both can be contained within the same
|
||||
context or different contexts. For example, if launching a job from the
|
||||
command line, a new JVM will be instantiated for each Job, and thus every
|
||||
job will have its own <classname>JobLauncher</classname>. However, if
|
||||
running from within a web container within the scope of an
|
||||
<classname>HttpRequest</classname>, there will usually be one
|
||||
<classname>JobLauncher</classname>, configured for asynchronous job
|
||||
launching, that multiple requests will invoke to launch their jobs.</para>
|
||||
|
||||
<section>
|
||||
<title>Running Jobs from the Command Line</title>
|
||||
@@ -421,29 +432,32 @@
|
||||
<classname>CommandLineJobRunner</classname>. It's important to note
|
||||
that this is just one way to bootstrap your application, but there are
|
||||
many ways to launch a Java process, and this class should in no way be
|
||||
viewed as definitive. It performs four tasks:</para>
|
||||
viewed as definitive. The <classname>CommandLineJobRunner</classname>
|
||||
performs four tasks:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Loads the appropriate Application Context</para>
|
||||
<para>Load the appropriate
|
||||
<classname>ApplicationContext</classname></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Parses command line arguments into JobParameters</para>
|
||||
<para>Parse command line arguments into
|
||||
<classname>JobParameters</classname></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Locates the appropriate job based on arguments</para>
|
||||
<para>Locate the appropriate job based on arguments</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Uses the JobLauncher provided in the application context to
|
||||
launch the job.</para>
|
||||
<para>Use the <classname>JobLauncher</classname> provided in the
|
||||
application context to launch the job.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>All of these tasks are accomplished based completely upon the
|
||||
arguments passed in. The following are required arguments:</para>
|
||||
<para>All of these tasks are accomplished using only the arguments
|
||||
passed in. The following are required arguments:</para>
|
||||
|
||||
<table>
|
||||
<title>CommandLineJobRunner arguments</title>
|
||||
@@ -479,22 +493,21 @@
|
||||
This example is using the same 'EndOfDay' example from <xref
|
||||
linkend="domain" />. The first argument is 'endOfDayJob.xml', which is
|
||||
the Spring <classname>ApplicationContext</classname> containing the
|
||||
Job. The second argument, 'endOfDay' represents the job name. The
|
||||
final argument, 'schedule.date=01-01-2008' will be converted into
|
||||
<classname>JobParameters</classname>. An example of the XML
|
||||
configuration is below:</para>
|
||||
<classname>Job</classname>. The second argument, 'endOfDay' represents
|
||||
the job name. The final argument, 'schedule.date=01-01-2008' will be
|
||||
converted into <classname>JobParameters</classname>. An example of the
|
||||
XML configuration is below:</para>
|
||||
|
||||
<programlisting> <bean id="endOfDay"
|
||||
class="org.springframework.batch.core.job.SimpleJob">
|
||||
<property name="steps">
|
||||
<bean id="step1" parent="simpleStep" />
|
||||
<programlisting> <job id="endOfDay">
|
||||
<steps>
|
||||
<step name="step1" parent="simpleStep" />
|
||||
<!-- Step details removed for clarity -->
|
||||
</property>
|
||||
</bean>
|
||||
</steps>
|
||||
</job>
|
||||
|
||||
<!-- Launcher details removed for clarity -->
|
||||
<bean id="jobLauncher"
|
||||
class="org.springframework.batch.core.launch.support.SimpleJobLauncher" /></programlisting>
|
||||
<beans: bean id="jobLauncher"
|
||||
class="org.springframework.batch.core.launch.support.SimpleJobLauncher" /></programlisting>
|
||||
|
||||
<para>This example is overly simplistic, since there are many more
|
||||
requirements to a run a batch job in Spring Batch in general, but it
|
||||
@@ -507,22 +520,23 @@
|
||||
<section>
|
||||
<title>ExitCodes</title>
|
||||
|
||||
<para>When launching a batch job from the command-line, it is often
|
||||
from an enterprise scheduler. Most schedulers are fairly dumb, and
|
||||
work only at the process level. Meaning, they only know about some
|
||||
<para>When launching a batch job from the command-line, an enterprise
|
||||
scheduler is often used. Most schedulers are fairly dumb and work only
|
||||
at the process level. This means that they only know about some
|
||||
operating system process such as a shell script that they're invoking.
|
||||
In this scenario, the only way to communicate back to the scheduler
|
||||
about the success or failure of a job is through return codes. A
|
||||
number is returned to a scheduler that is told how to interpret the
|
||||
result. In the simple case: 0 is success and 1 is failure. However,
|
||||
there may be scenarios such as: If job A returns 4 kick off job B, if
|
||||
it returns 5 kick off job C. This type of behavior is configured at
|
||||
the scheduler level, but it is important that a processing framework
|
||||
such as Spring Batch provide a way to return a numeric representation
|
||||
of of the 'Exit Code' for a particular batch job. In Spring Batch this
|
||||
is encapsulated within an <classname>ExitStatus</classname>, which is
|
||||
covered in more detail in Chapter 5. For the purposes of discussing
|
||||
exit codes, the only important thing to know is that an
|
||||
return code is a number that is returned to a scheduler by the process
|
||||
that indicates the result of the run. In the simplest case: 0 is
|
||||
success and 1 is failure. However, there may be more complex
|
||||
scenarios: If job A returns 4 kick off job B, and if it returns 5 kick
|
||||
off job C. This type of behavior is configured at the scheduler level,
|
||||
but it is important that a processing framework such as Spring Batch
|
||||
provide a way to return a numeric representation of the 'Exit Code'
|
||||
for a particular batch job. In Spring Batch this is encapsulated
|
||||
within an <classname>ExitStatus</classname>, which is covered in more
|
||||
detail in Chapter 5. For the purposes of discussing exit codes, the
|
||||
only important thing to know is that an
|
||||
<classname>ExitStatus</classname> has an exit code property that is
|
||||
set by the framework (or the developer) and is returned as part of the
|
||||
<classname>JobExecution</classname> returned from the
|
||||
@@ -554,7 +568,7 @@
|
||||
it will be injected into the runner after the context is created. All
|
||||
that needs to be done to provide your own
|
||||
<classname>ExitCodeMapper</classname> is to declare the implementation
|
||||
as a root level bean, and ensure it's part of the
|
||||
as a root level bean and ensure that it is part of the
|
||||
<classname>ApplicationContext</classname> that is loaded by the
|
||||
runner.</para>
|
||||
</section>
|
||||
@@ -589,12 +603,12 @@
|
||||
|
||||
<para>A <classname>JobLauncher</classname> uses the
|
||||
<classname>JobRepository</classname> to create new
|
||||
<classname>JobExecution</classname> objects, and run them.
|
||||
<classname>JobExecution</classname> objects and run them.
|
||||
<classname>Job</classname> and <classname>Step</classname> implementations
|
||||
later use the same <classname>JobRepository</classname> for basic updates
|
||||
of the same executions during the running of a <classname>Job</classname>.
|
||||
The basic operations suffice for simple scenarios. However, in a large
|
||||
batch environment with hundreds of batch jobs and complex scheduling
|
||||
The basic operations suffice for simple scenarios, but in a large batch
|
||||
environment with hundreds of batch jobs and complex scheduling
|
||||
requirements, more advanced access of the meta data is required:</para>
|
||||
|
||||
<mediaobject>
|
||||
@@ -654,9 +668,10 @@
|
||||
|
||||
<para><link linkend="repositoryTablePrefix">Earlier in this
|
||||
chapter</link>, it was mentioned that the table prefix of the
|
||||
JobRepository can be modified to allow for different versions or
|
||||
schemas. Because the JobExplorer is working with the same tables, it too
|
||||
needs the ability to set a prefix:</para>
|
||||
<classname>JobRepository</classname> can be modified to allow for
|
||||
different versions or schemas. Because the
|
||||
<classname>JobExplorer</classname> is working with the same tables, it
|
||||
too needs the ability to set a prefix:</para>
|
||||
|
||||
<programlisting>
|
||||
<bean id="jobExplorer" class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean"
|
||||
@@ -741,35 +756,43 @@
|
||||
self-explanatory, and more detailed explanations can be found on the
|
||||
<ulink
|
||||
url="http://static.springframework.org/spring-batch/apidocs/org/springframework/batch/core/launch/JobOperator.html">javadoc
|
||||
of the interface</ulink>. However, the 'startNextInstance' method is
|
||||
worth noting. This method will always start a new instance of a Job.
|
||||
of the interface</ulink>. However, the
|
||||
<methodname>startNextInstance</methodname> method is worth noting. This
|
||||
method will always start a new instance of a <classname>Job</classname>.
|
||||
This can be extremely useful if there are serious issues in a
|
||||
<classname>Job</classname>Execution, and the <classname>Job</classname>
|
||||
<classname>JobExecution</classname> and the <classname>Job</classname>
|
||||
needs to be started over again from the beginning. Unlike
|
||||
<classname>JobLauncher</classname> though, which requires a new
|
||||
<classname>JobParameters</classname> that will trigger a new JobInstance
|
||||
if they are different than any previous one, the startNextInstance
|
||||
method will use the JobParametersIncrementer tied to the Job to force
|
||||
the <classname>Job</classname> to a new instance:</para>
|
||||
<classname>JobParameters</classname> object that will trigger a new
|
||||
<classname>JobInstance</classname> if the parameters are different from
|
||||
any previous set of parameters, the
|
||||
<methodname>startNextInstance</methodname> method will use the
|
||||
<classname>JobParametersIncrementer</classname> tied to the
|
||||
<classname>Job</classname> to force the <classname>Job</classname> to a
|
||||
new instance:</para>
|
||||
|
||||
<programlisting>
|
||||
public interface JobParametersIncrementer {
|
||||
|
||||
JobParameters getNext(JobParameters parameters);
|
||||
|
||||
}
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>The contract of <classname>JobParametersIncrementer</classname> is
|
||||
that, given a <link linkend="jobParameters">JobParameters</link>, it
|
||||
will return the 'next' parameter by incrementing any values it may
|
||||
contain. This strategy is useful because the framework has no way of
|
||||
knowing what changes to the JobParameters make it the 'next' instance.
|
||||
For example, if the only value in JobParameters is a date, and the next
|
||||
instance should be created, should that value be incremented by one day?
|
||||
Or one week? (if the job is weekly for instance) The same can be said
|
||||
for any numerical values that help to identify the Job, as shown
|
||||
below:</para>
|
||||
that, given a <link
|
||||
linkend="jobParameters"><classname>JobParameters</classname></link>
|
||||
object, it will return the 'next' <classname>JobParameters</classname>
|
||||
object by incrementing any necessary values it may contain. This
|
||||
strategy is useful because the framework has no way of knowing what
|
||||
changes to the <classname>JobParameters</classname> make it the 'next'
|
||||
instance. For example, if the only value in
|
||||
<classname>JobParameters</classname> is a date, and the next instance
|
||||
should be created, should that value be incremented by one day? Or one
|
||||
week (if the job is weekly for instance)? The same can be said for any
|
||||
numerical values that help to identify the <classname>Job</classname>,
|
||||
as shown below:</para>
|
||||
|
||||
<programlisting>
|
||||
public class SampleIncrementer implements JobParametersIncrementer {
|
||||
@@ -786,12 +809,13 @@
|
||||
</programlisting>
|
||||
|
||||
<para>In this example, the value with a key of 'run.id' is used to
|
||||
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
|
||||
associated with Job via the 'incrementer' attribute in the
|
||||
namespace:</para>
|
||||
discriminate between <classname>JobInstances</classname>. If the
|
||||
<classname>JobParameters</classname> passed in is null, it can be
|
||||
assumed that the <classname>Job</classname> has never been run before
|
||||
and thus its initial state can be returned. However, if not, the old
|
||||
value is obtained, incremented by one, and returned. An incrementer can
|
||||
be associated with <classname>Job</classname> via the 'incrementer'
|
||||
attribute in the namespace:</para>
|
||||
|
||||
<programlisting>
|
||||
<job id="footballJob" <emphasis role="bold">incrementer="sampleIncrementer"</emphasis>>
|
||||
@@ -819,8 +843,8 @@
|
||||
<para>The shutdown is not immediate, since there is no way to force
|
||||
immediate shutdown, especially if the execution is currently in
|
||||
developer code that the framework has no control over, such as a
|
||||
business service. What it does mean, is that as soon as control is
|
||||
returned back to the framework, it will set the status of the current
|
||||
business service. However, as soon as control is returned back to the
|
||||
framework, it will set the status of the current
|
||||
<classname>StepExecution</classname> to
|
||||
<classname>BatchStatus.STOPPED</classname>, save it, then do the same
|
||||
for the <classname>JobExecution</classname> before finishing.</para>
|
||||
|
||||
@@ -477,7 +477,7 @@
|
||||
processing locations and vice versa. File moving utilities are beyond
|
||||
the scope of the spring batch architecture but it is not unusual for
|
||||
batch job streams to include file moving utilities as steps in the job
|
||||
stream. Its sufficient that the batch architecture only needs to know
|
||||
stream. It is sufficient that the batch architecture only needs to know
|
||||
how to locate the files to be processed. Spring Batch begins the process
|
||||
of feeding the data into the pipe from this starting point. However,
|
||||
<ulink
|
||||
@@ -800,7 +800,7 @@
|
||||
<programlisting>
|
||||
FlatFileItemReader<Player> itemReader = new FlatFileItemReader<Player>();
|
||||
itemReader.setResource(new FileSystemResource("resources/players.csv"));
|
||||
//DelimitedLineTokenizer defaults to comma as it's delimiter
|
||||
//DelimitedLineTokenizer defaults to comma as its delimiter
|
||||
LineMapper<Player> lineMapper = new DefaultLineMapper<Player>();
|
||||
lineMapper.setLineTokenizer(new DelimitedLineTokenizer());
|
||||
lineMapper.setFieldSetMapper(new PlayerFieldSetMapper());
|
||||
@@ -973,7 +973,7 @@
|
||||
|
||||
<para>All of the file reading examples up to this point have all made
|
||||
a key assumption for simplicity's sake: all of the records in a file
|
||||
have the same format. However, this may not always be the case. Its
|
||||
have the same format. However, this may not always be the case. It is
|
||||
very common that a file might have records with different formats that
|
||||
need to be tokenized differently and mapped to different objects. The
|
||||
following excerpt from a file illustrates this:</para>
|
||||
@@ -1219,7 +1219,7 @@
|
||||
<title>Simplified File Writing Example</title>
|
||||
|
||||
<para>Now that the <classname>LineAggregator</classname> interface and
|
||||
it's most basic implementation,
|
||||
its most basic implementation,
|
||||
<classname>PassThroughLineAggregator</classname>, have been defined,
|
||||
the basic flow of writing can be explained:</para>
|
||||
|
||||
@@ -2408,9 +2408,9 @@
|
||||
existing service needs to act as an <classname>ItemReader</classname> or
|
||||
<classname>ItemWriter</classname>, either to satisfy the dependency of
|
||||
another Spring Batch class, or because it truly is the main
|
||||
<classname>ItemReader</classname> for a step. Its fairly trivial to write
|
||||
an adaptor class for each service that needs wrapping, but because its
|
||||
such a common concern, Spring Batch provides implementations:
|
||||
<classname>ItemReader</classname> for a step. It is fairly trivial to
|
||||
write an adaptor class for each service that needs wrapping, but because
|
||||
it is such a common concern, Spring Batch provides implementations:
|
||||
<classname>ItemReaderAdapter</classname> and
|
||||
<classname>ItemWriterAdapter</classname>. Both classes implement the
|
||||
standard Spring method invoking the delegate pattern and are fairly simple
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
respectively. <classname>ExecutionContext</classname> maps to both
|
||||
BATCH_JOB_EXECUTION_CONTEXT and BATCH_STEP_EXECUTION_CONTEXT. The
|
||||
<classname>JobRepository</classname> is responsible for saving and storing
|
||||
each Java object into it's correct table. The following appendix describes
|
||||
each Java object into its correct table. The following appendix describes
|
||||
the meta-data tables in detail, along with many of the design decisions
|
||||
that were made when creating them. When viewing the various table creation
|
||||
statements below, it is important to realize that the data types used are
|
||||
@@ -49,7 +49,7 @@
|
||||
to try and save the value, if the version number has change it will
|
||||
throw <classname>OptimisticLockingFailureException</classname>,
|
||||
indicating there has been an error with concurrent access. This check is
|
||||
necessary, since even though different batch jobs may be running in
|
||||
necessary since, even though different batch jobs may be running in
|
||||
different machines, they are all using the same database tables.</para>
|
||||
</section>
|
||||
|
||||
@@ -57,11 +57,11 @@
|
||||
<title>Identity</title>
|
||||
|
||||
<para>BATCH_JOB_INSTANCE, BATCH_JOB_EXECUTION, and BATCH_STEP_EXECUTION
|
||||
each contain columns ending in _ID, which act as primary keys for their
|
||||
respective tables. However, they are not database generated keys, but
|
||||
rather are generated by separate sequences. This is necessary because
|
||||
after inserting one of the domain objects into the database, the key it
|
||||
is given needs to be set on the actual object, so that they can be
|
||||
each contain columns ending in _ID. These fields act as primary keys for
|
||||
their respective tables. However, they are not database generated keys,
|
||||
but rather they are generated by separate sequences. This is necessary
|
||||
because after inserting one of the domain objects into the database, the
|
||||
key it is given needs to be set on the actual object so that they can be
|
||||
uniquely identified in Java. Newer database drivers (Jdbc 3.0 and up)
|
||||
support this feature with database generated keys, but rather than
|
||||
requiring it, sequences were used. Each variation of the schema will
|
||||
@@ -431,8 +431,8 @@ INSERT INTO BATCH_JOB_SEQ values(0);</programlisting>
|
||||
<para>The BATCH_JOB_EXECUTION_CONTEXT table holds all information relevant
|
||||
to an <classname>Job</classname>'s
|
||||
<classname>ExecutionContext</classname>. There is exactly one
|
||||
<classname>ExecutionContext</classname> per
|
||||
<classname>StepExecution</classname>, and it contains all of the job-level
|
||||
<classname>Job</classname> <classname>ExecutionContext</classname> per
|
||||
<classname>JobExecution</classname>, and it contains all of the job-level
|
||||
data that is needed for a particular job execution. This data typically
|
||||
represents the state that must be retrieved after a failure so that a
|
||||
<classname>JobInstance</classname> can 'start from where it left
|
||||
|
||||
Reference in New Issue
Block a user