BATCH-1065: update docos with stop transition
This commit is contained in:
@@ -353,7 +353,7 @@
|
||||
<imageobject role="fo">
|
||||
<imagedata align="center"
|
||||
fileref="images/job-launcher-sequence-sync.png" scale="70"
|
||||
scale="80" width="66%" />
|
||||
width="66%" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
@@ -375,7 +375,7 @@
|
||||
<imageobject role="fo">
|
||||
<imagedata align="center"
|
||||
fileref="images/job-launcher-sequence-async.png" scale="70"
|
||||
scale="80" width="66%" />
|
||||
width="66%" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
@@ -590,7 +590,7 @@
|
||||
|
||||
<mediaobject>
|
||||
<imageobject role="html">
|
||||
<imagedata align="center" fileref="images/job-repository.png" scale=""
|
||||
<imagedata align="center" fileref="images/job-repository.png"
|
||||
width="40%" />
|
||||
</imageobject>
|
||||
|
||||
@@ -614,7 +614,7 @@
|
||||
<mediaobject>
|
||||
<imageobject role="html">
|
||||
<imagedata align="center" fileref="images/job-repository-advanced.png"
|
||||
scale="" width="65%" />
|
||||
width="65%" />
|
||||
</imageobject>
|
||||
|
||||
<imageobject role="fo">
|
||||
|
||||
@@ -56,16 +56,16 @@
|
||||
<para>Below is a code representation of the same concepts shown
|
||||
above:</para>
|
||||
|
||||
<programlisting>
|
||||
<programlisting><![CDATA[
|
||||
List items = new Arraylist();
|
||||
for(int i = 0; i < commitInterval; i++){
|
||||
for(int i = 0; i < commitInterval; i++){
|
||||
Object item = itemReader.read()
|
||||
Object processedItem = itemProcessor.process(item);
|
||||
items.add(processedItem);
|
||||
}
|
||||
itemWriter.write(items);
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<section>
|
||||
<title>Configuring a Step</title>
|
||||
@@ -75,14 +75,14 @@
|
||||
potentially contain many collaborators. In order to ease configuration,
|
||||
the Spring Batch namespace can be used:</para>
|
||||
|
||||
<programlisting>
|
||||
<job id="sampleJob">
|
||||
<step id="step1" job-repository="jobRepository" transaction-manager="transactionManager">
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="10"/>
|
||||
</step>
|
||||
</job>
|
||||
<programlisting><![CDATA[
|
||||
<job id="sampleJob">
|
||||
<step id="step1" job-repository="jobRepository" transaction-manager="transactionManager">
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="10"/>
|
||||
</step>
|
||||
</job>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para>The configuration above represents the only required dependencies
|
||||
to create a item-oriented step:<itemizedlist>
|
||||
@@ -133,16 +133,16 @@
|
||||
reference it from multiple jobs. This can be achieved with the 'ref'
|
||||
attribute:</para>
|
||||
|
||||
<programlisting>
|
||||
<job id="sampleJob">
|
||||
<step id="step1" <emphasis role="bold">ref="standaloneStep"</emphasis> />
|
||||
</job>
|
||||
<programlisting><![CDATA[
|
||||
<job id="sampleJob">
|
||||
<step id="step1" ]]><emphasis role="bold">ref="standaloneStep"</emphasis><![CDATA[ />
|
||||
</job>
|
||||
|
||||
<step id="standaloneStep" job-repository="jobRepository" transaction-manager="transactionManager">
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="10"/>
|
||||
</step>
|
||||
<step id="standaloneStep" job-repository="jobRepository" transaction-manager="transactionManager">
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="10"/>
|
||||
</step>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para>It should be noted that the id attribute is still required on the
|
||||
step within the job element. This is for two reasons:</para>
|
||||
@@ -177,15 +177,15 @@
|
||||
number of items that are processed within a commit can be
|
||||
configured.</para>
|
||||
|
||||
<programlisting>
|
||||
<job id="sampleJob">
|
||||
<step id="step1" job-repository="jobRepository" transaction-manager="transactionManager">
|
||||
<tasklet reader="itemReader" writer="itemWriter" <emphasis
|
||||
role="bold">commit-interval="10"</emphasis>/>
|
||||
</step>
|
||||
</job>
|
||||
<programlisting><![CDATA[
|
||||
<job id="sampleJob">
|
||||
<step id="step1" job-repository="jobRepository" transaction-manager="transactionManager">
|
||||
<tasklet reader="itemReader" writer="itemWriter" ]]><emphasis
|
||||
role="bold">commit-interval="10"</emphasis><![CDATA[/>
|
||||
</step>
|
||||
</job>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para>In the example above, 10 items will be processed within each
|
||||
transaction. At the beginning of processing a transaction is begun, and
|
||||
@@ -217,13 +217,13 @@
|
||||
as a <classname>Step</classname> that can be run infinitely. Below is
|
||||
an example start limit configuration:</para>
|
||||
|
||||
<programlisting>
|
||||
<step id="step1">
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="10" <emphasis
|
||||
role="bold">start-limit="1"</emphasis>/>
|
||||
</step>
|
||||
<programlisting><![CDATA[
|
||||
<step id="step1">
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="10" ]]><emphasis
|
||||
role="bold">start-limit="1"</emphasis><![CDATA[/>
|
||||
</step>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para>The simple step above can be run only once. Attempting to run it
|
||||
again will cause an exception to be thrown. It should be noted that
|
||||
@@ -243,35 +243,35 @@
|
||||
successfully, will be skipped. Setting allow-start-if-complete to
|
||||
"true" overrides this so that the step will always run:</para>
|
||||
|
||||
<programlisting>
|
||||
<step id="step1">
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="10"
|
||||
<emphasis role="bold">allow-start-if-complete="true"</emphasis>/>
|
||||
</step>
|
||||
<programlisting><![CDATA[
|
||||
<step id="step1">
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="10"
|
||||
]]><emphasis role="bold">allow-start-if-complete="true"</emphasis><![CDATA[/>
|
||||
</step>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Step restart configuration example</title>
|
||||
|
||||
<programlisting>
|
||||
<job id="footballJob" restartable="true">
|
||||
<step id="playerload" next="gameLoad">
|
||||
<tasklet reader="playerFileItemReader" writer="playerWriter"
|
||||
commit-interval="10" />
|
||||
</step>
|
||||
<step id="gameLoad" next="playerSummarization">
|
||||
<tasklet reader="gameFileItemReader" writer="gameWriter"
|
||||
commit-interval="10" allow-start-if-complete="true"/>
|
||||
</step>
|
||||
<step id="playerSummarization">
|
||||
<tasklet reader="playerSummarizationSource" writer="summaryWriter"
|
||||
commit-interval="10" start-limit="3"/>
|
||||
</step>
|
||||
</job>
|
||||
<programlisting><![CDATA[
|
||||
<job id="footballJob" restartable="true">
|
||||
<step id="playerload" next="gameLoad">
|
||||
<tasklet reader="playerFileItemReader" writer="playerWriter"
|
||||
commit-interval="10" />
|
||||
</step>
|
||||
<step id="gameLoad" next="playerSummarization">
|
||||
<tasklet reader="gameFileItemReader" writer="gameWriter"
|
||||
commit-interval="10" allow-start-if-complete="true"/>
|
||||
</step>
|
||||
<step id="playerSummarization">
|
||||
<tasklet reader="playerSummarizationSource" writer="summaryWriter"
|
||||
commit-interval="10" start-limit="3"/>
|
||||
</step>
|
||||
</job>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para>The above example configuration is for a job that loads in
|
||||
information about football games and summarizes them. It contains
|
||||
@@ -384,17 +384,17 @@
|
||||
loaded because it was formatted incorrectly or was missing necessary
|
||||
information, then there probably won't be issues. Usually these bad
|
||||
records are logged as well, which will be covered later when discussing
|
||||
listeners.<programlisting>
|
||||
<step id="step1">
|
||||
<tasklet reader="flatFileItemReader" writer="itemWriter" commit-interval="10" <emphasis
|
||||
role="bold">skip-limit="10"</emphasis>>
|
||||
<emphasis role="bold"><skippable-exception-classes>
|
||||
listeners.<programlisting><![CDATA[
|
||||
<step id="step1">
|
||||
<tasklet reader="flatFileItemReader" writer="itemWriter" commit-interval="10" ]]><emphasis
|
||||
role="bold">skip-limit="10"</emphasis><![CDATA[>
|
||||
]]><emphasis role="bold"><skippable-exception-classes>
|
||||
org.springframework.batch.item.file.FlatFileParseException
|
||||
</skippable-exception-classes></emphasis>
|
||||
</tasklet>
|
||||
</step>
|
||||
</skippable-exception-classes></emphasis><![CDATA[
|
||||
</tasklet>
|
||||
</step>
|
||||
|
||||
</programlisting></para>
|
||||
]]></programlisting></para>
|
||||
|
||||
<para>In this example, a <classname>FlatFileItemReader</classname> is
|
||||
used, and if at any point a
|
||||
@@ -411,20 +411,20 @@
|
||||
<classname>Job</classname> to fail. In certain scenarios this may be the
|
||||
correct behavior. However, in other scenarios it may be easier to
|
||||
identify which exceptions should cause failure and skip everything
|
||||
else:<programlisting>
|
||||
<step id="step1">
|
||||
<tasklet reader="flatFileItemReader" writer="itemWriter" commit-interval="10" <emphasis
|
||||
role="bold">skip-limit="10"</emphasis>>
|
||||
<emphasis role="bold"> <skippable-exception-classes>
|
||||
else:<programlisting><![CDATA[
|
||||
<step id="step1">
|
||||
<tasklet reader="flatFileItemReader" writer="itemWriter" commit-interval="10" ]]><emphasis
|
||||
role="bold">skip-limit="10"</emphasis><![CDATA[>
|
||||
]]><emphasis role="bold"> <skippable-exception-classes>
|
||||
java.lang.Exception
|
||||
</skippable-exception-classes>
|
||||
<fatal-exception-classes>
|
||||
java.io.FileNotFoundException
|
||||
</fatal-exception-classes>
|
||||
</emphasis> </tasklet>
|
||||
</step>
|
||||
</emphasis><![CDATA[ </tasklet>
|
||||
</step>
|
||||
|
||||
</programlisting></para>
|
||||
]]></programlisting></para>
|
||||
|
||||
<para>By setting the skippable exceptions to
|
||||
<classname>java.lang.Exception</classname>, any exception that is thrown
|
||||
@@ -446,17 +446,17 @@
|
||||
process holds a lock on, waiting and trying again might result in
|
||||
success. In this case, retry should be configured:</para>
|
||||
|
||||
<programlisting>
|
||||
<step id="step1">
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="2" <emphasis
|
||||
role="bold">retry-limit="3"</emphasis>>
|
||||
<emphasis role="bold"><retryable-exception-classes>
|
||||
<programlisting><![CDATA[
|
||||
<step id="step1">
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="2" ]]><emphasis
|
||||
role="bold">retry-limit="3"</emphasis><![CDATA[>
|
||||
]]><emphasis role="bold"><retryable-exception-classes>
|
||||
org.springframework.dao.DeadlockLoserDataAccessException
|
||||
</retryable-exception-classes></emphasis>
|
||||
</tasklet>
|
||||
</step>
|
||||
</retryable-exception-classes></emphasis><![CDATA[
|
||||
</tasklet>
|
||||
</step>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para>The <classname>Step</classname> allows a limit for the number of
|
||||
times an individual item can be retried, and a list of exceptions that
|
||||
@@ -481,14 +481,14 @@
|
||||
symbol will indicate that that exception should not cause
|
||||
rollback.</para>
|
||||
|
||||
<programlisting>
|
||||
<step id="step1">
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="2" skip-limit="1"
|
||||
<emphasis role="bold">transaction-attribute="+org.springframework.batch.item.validator.ValidationException"</emphasis>>
|
||||
</tasklet>
|
||||
</step>
|
||||
<programlisting><![CDATA[
|
||||
<step id="step1">
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="2" skip-limit="1"
|
||||
]]><emphasis role="bold">transaction-attribute="+org.springframework.batch.item.validator.ValidationException"</emphasis><![CDATA[>
|
||||
</tasklet>
|
||||
</step>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para>Transaction attributes can be used to control multiple other
|
||||
settings such as isolation and propagation behavior. More information on
|
||||
@@ -508,14 +508,14 @@
|
||||
this reason, the step can be configured to not buffer the
|
||||
items:</para>
|
||||
|
||||
<programlisting>
|
||||
<step id="step1">
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="2" skip-limit="1"
|
||||
<emphasis role="bold">is-reader-transactional-queue="true"</emphasis>>
|
||||
</tasklet>
|
||||
</step>
|
||||
<programlisting><![CDATA[
|
||||
<step id="step1">
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="2" skip-limit="1"
|
||||
]]><emphasis role="bold">is-reader-transactional-queue="true"</emphasis><![CDATA[>
|
||||
</tasklet>
|
||||
</step>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -540,27 +540,27 @@
|
||||
can be registered on the <classname>Step</classname> through the
|
||||
'streams' element, as illustrated below:</para>
|
||||
|
||||
<programlisting>
|
||||
<step id="step1">
|
||||
<tasklet reader="itemReader" writer="compositeWriter" commit-interval="2">
|
||||
<emphasis role="bold"><streams>
|
||||
<programlisting><![CDATA[
|
||||
<step id="step1">
|
||||
<tasklet reader="itemReader" writer="compositeWriter" commit-interval="2">
|
||||
]]><emphasis role="bold"><streams>
|
||||
<stream ref="fileItemWriter1"/>
|
||||
<stream ref="fileItemWriter2"/>
|
||||
</streams></emphasis>
|
||||
</tasklet>
|
||||
</step>
|
||||
</streams></emphasis><![CDATA[
|
||||
</tasklet>
|
||||
</step>
|
||||
|
||||
<beans:bean id="compositeWriter"
|
||||
class="org.springframework.batch.item.support.CompositeItemWriter">
|
||||
<beans:property name="delegates">
|
||||
<beans:list>
|
||||
<beans:ref bean="fileItemWriter1" />
|
||||
<beans:ref bean="fileItemWriter2" />
|
||||
</beans:list>
|
||||
</beans:property>
|
||||
</beans:bean>
|
||||
<beans:bean id="compositeWriter"
|
||||
class="org.springframework.batch.item.support.CompositeItemWriter">
|
||||
<beans:property name="delegates">
|
||||
<beans:list>
|
||||
<beans:ref bean="fileItemWriter1" />
|
||||
<beans:ref bean="fileItemWriter2" />
|
||||
</beans:list>
|
||||
</beans:property>
|
||||
</beans:bean>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para>In the example above, the
|
||||
<classname>CompositeItemWriter</classname> is not an
|
||||
@@ -590,15 +590,15 @@
|
||||
interface (or an extension thereof) can be applied to a step via the
|
||||
listeners element:</para>
|
||||
|
||||
<programlisting>
|
||||
<step id="step1">
|
||||
<tasklet reader="reader" writer="writer" commit-interval="10"/>
|
||||
<listeners>
|
||||
<listener ref="stepListener"/>
|
||||
</listeners>
|
||||
</step>
|
||||
<programlisting><![CDATA[
|
||||
<step id="step1">
|
||||
<tasklet reader="reader" writer="writer" commit-interval="10"/>
|
||||
<listeners>
|
||||
<listener ref="stepListener"/>
|
||||
</listeners>
|
||||
</step>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para>In addition to the <classname>StepListener</classname> interfaces,
|
||||
annotations are provided to address the same concerns.</para>
|
||||
@@ -611,7 +611,7 @@
|
||||
for notification before a <classname>Step</classname> is started and
|
||||
after it has ends, whether it ended normally or failed:</para>
|
||||
|
||||
<programlisting>
|
||||
<programlisting><![CDATA[
|
||||
public interface StepExecutionListener extends StepListener {
|
||||
|
||||
void beforeStep(StepExecution stepExecution);
|
||||
@@ -619,7 +619,7 @@
|
||||
ExitStatus afterStep(StepExecution stepExecution);
|
||||
}
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para><classname>ExitStatus</classname> is the return type of
|
||||
<methodname>afterStep</methodname> in order to allow listeners the
|
||||
@@ -648,12 +648,12 @@
|
||||
useful to perform logic before a chunk begins processing or after a
|
||||
chunk has completed:</para>
|
||||
|
||||
<programlisting> public interface ChunkListener extends StepListener {
|
||||
<programlisting><![CDATA[ public interface ChunkListener extends StepListener {
|
||||
|
||||
void beforeChunk();
|
||||
|
||||
void afterChunk();
|
||||
}</programlisting>
|
||||
}]]></programlisting>
|
||||
|
||||
<para>The <methodname>beforeChunk</methodname> method is called after
|
||||
the transaction is started, but before <methodname>read</methodname>
|
||||
@@ -682,14 +682,14 @@
|
||||
<para>When discussing skip logic above, it was mentioned that it may
|
||||
be beneficial to log out skipped records, so that they can be deal
|
||||
with later. In the case of read errors, this can be done with an
|
||||
<classname>ItemReaderListener:</classname><programlisting> public interface ItemReadListener<T> extends StepListener {
|
||||
<classname>ItemReaderListener:</classname><programlisting><![CDATA[ public interface ItemReadListener<T> extends StepListener {
|
||||
|
||||
void beforeRead();
|
||||
|
||||
void afterRead(T item);
|
||||
|
||||
void onReadError(Exception ex);
|
||||
}</programlisting></para>
|
||||
}]]></programlisting></para>
|
||||
|
||||
<para>The <methodname>beforeRead</methodname> method will be called
|
||||
before each call to <methodname>read</methodname> on the
|
||||
@@ -724,14 +724,14 @@
|
||||
<para>Just as with the <classname>ItemReadListener</classname>, the
|
||||
processing of an item can be 'listened' to:</para>
|
||||
|
||||
<programlisting> public interface ItemProcessListener<T, S> extends StepListener {
|
||||
<programlisting><![CDATA[ public interface ItemProcessListener<T, S> extends StepListener {
|
||||
|
||||
void beforeProcess(T item);
|
||||
|
||||
void afterProcess(T item, S result);
|
||||
|
||||
void onProcessError(T item, Exception e);
|
||||
}</programlisting>
|
||||
}]]></programlisting>
|
||||
|
||||
<para>The <methodname>beforeProcess</methodname> method will be called
|
||||
before <methodname>process</methodname> on the
|
||||
@@ -766,14 +766,14 @@
|
||||
<para>The writing of an item can be 'listened' to with the
|
||||
<classname>ItemWriteListener</classname>:</para>
|
||||
|
||||
<programlisting> public interface ItemWriteListener<S> extends StepListener {
|
||||
<programlisting><![CDATA[ public interface ItemWriteListener<S> extends StepListener {
|
||||
|
||||
void beforeWrite(List<? extends S> items);
|
||||
void beforeWrite(List<? extends S> items);
|
||||
|
||||
void afterWrite(List<? extends S> items);
|
||||
void afterWrite(List<? extends S> items);
|
||||
|
||||
void onWriteError(Exception exception, List<? extends S> items);
|
||||
}</programlisting>
|
||||
void onWriteError(Exception exception, List<? extends S> items);
|
||||
}]]></programlisting>
|
||||
|
||||
<para>The <methodname>beforeWrite</methodname> method will be called
|
||||
before <methodname>write</methodname> on the
|
||||
@@ -813,8 +813,8 @@
|
||||
this reason, there is a separate interface for tracking skipped
|
||||
items:</para>
|
||||
|
||||
<programlisting>
|
||||
public interface SkipListener<T,S> extends StepListener {
|
||||
<programlisting><![CDATA[
|
||||
public interface SkipListener<T,S> extends StepListener {
|
||||
|
||||
void onSkipInRead(Throwable t);
|
||||
|
||||
@@ -823,7 +823,7 @@
|
||||
void onSkipInWrite(S item, Throwable t);
|
||||
}
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para><methodname>onSkipInRead</methodname> will be called whenever an
|
||||
item is skipped while reading. It should be noted that rollbacks may
|
||||
@@ -899,10 +899,10 @@
|
||||
<classname>Tasklet</classname> object; no 'tasklet' element is needed
|
||||
within the 'step':</para>
|
||||
|
||||
<programlisting>
|
||||
<step id="step1" <emphasis role="bold">tasklet="myTasklet"</emphasis> />
|
||||
<programlisting><![CDATA[
|
||||
<step id="step1" ]]><emphasis role="bold">tasklet="myTasklet"</emphasis><![CDATA[ />
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<note>
|
||||
<para><classname>TaskletStep</classname> will automatically register the
|
||||
@@ -923,15 +923,15 @@
|
||||
this class without having to write an adapter for the
|
||||
<classname>Tasklet</classname> interface:</para>
|
||||
|
||||
<programlisting>
|
||||
<bean id="myTasklet" class="org.springframework.batch.core.step.tasklet.TaskletAdapter">
|
||||
<property name="targetObject">
|
||||
<bean class="org.mycompany.FooDao">
|
||||
</property>
|
||||
<property name="targetMethod" value-"updateFoo" />
|
||||
</bean>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="myTasklet" class="org.springframework.batch.core.step.tasklet.TaskletAdapter">
|
||||
<property name="targetObject">
|
||||
<bean class="org.mycompany.FooDao">
|
||||
</property>
|
||||
<property name="targetMethod" value-"updateFoo" />
|
||||
</bean>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
@@ -946,7 +946,7 @@
|
||||
project, is a <classname>Tasklet</classname> implementation with just
|
||||
such a responsibility:</para>
|
||||
|
||||
<programlisting> public class FileDeletingTasklet implements Tasklet, InitializingBean {
|
||||
<programlisting><![CDATA[ public class FileDeletingTasklet implements Tasklet, InitializingBean {
|
||||
|
||||
private Resource directory;
|
||||
|
||||
@@ -955,7 +955,7 @@
|
||||
Assert.state(dir.isDirectory());
|
||||
|
||||
File[] files = dir.listFiles();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
boolean deleted = files[i].delete();
|
||||
if (!deleted) {
|
||||
throw new UnexpectedJobExecutionException("Could not delete file " + files[i].getPath());
|
||||
@@ -971,7 +971,7 @@
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(directory, "directory must be set");
|
||||
}
|
||||
}</programlisting>
|
||||
}]]></programlisting>
|
||||
|
||||
<para>The above <classname>Tasklet</classname> implementation will
|
||||
delete all files within a given directory. It should be noted that the
|
||||
@@ -979,22 +979,22 @@
|
||||
that is left is to reference the <classname>Tasklet</classname> from the
|
||||
<classname>Step</classname>:</para>
|
||||
|
||||
<programlisting>
|
||||
<job id="taskletJob">
|
||||
<step id="deleteFilesInDir" tasklet="fileDeletingTasklet"/>
|
||||
</job>
|
||||
<programlisting><![CDATA[
|
||||
<job id="taskletJob">
|
||||
<step id="deleteFilesInDir" tasklet="fileDeletingTasklet"/>
|
||||
</job>
|
||||
|
||||
<bean id="fileDeletingTasklet"
|
||||
class="org.springframework.batch.sample.tasklet.FileDeletingTasklet">
|
||||
<property name="directoryResource">
|
||||
<bean id="directory"
|
||||
class="org.springframework.core.io.FileSystemResource">
|
||||
<constructor-arg value="target/test-outputs/test-dir" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
<bean id="fileDeletingTasklet"
|
||||
class="org.springframework.batch.sample.tasklet.FileDeletingTasklet">
|
||||
<property name="directoryResource">
|
||||
<bean id="directory"
|
||||
class="org.springframework.core.io.FileSystemResource">
|
||||
<constructor-arg value="target/test-outputs/test-dir" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -1031,18 +1031,18 @@
|
||||
<para>This can be achieved using the 'next' attribute of the step
|
||||
element:</para>
|
||||
|
||||
<para><programlisting>
|
||||
<job id="job">
|
||||
<step id="stepA" next="stepB" />
|
||||
<step id="stepB" next="stepC"/>
|
||||
<step id="stepC" />
|
||||
</job>
|
||||
<para><programlisting><![CDATA[
|
||||
<job id="job">
|
||||
<step id="stepA" next="stepB" />
|
||||
<step id="stepB" next="stepC"/>
|
||||
<step id="stepC" />
|
||||
</job>
|
||||
|
||||
</programlisting>In the scenario above, 'step A' will execute first because it
|
||||
is the first <classname>Step</classname> listed. If 'step A' completes
|
||||
normally, then 'step B' will execute, and so on. However, if 'step A'
|
||||
fails, then the entire <classname>Job</classname> will fail and 'step B'
|
||||
will not execute.</para>
|
||||
]]></programlisting>In the scenario above, 'step A' will execute first because
|
||||
it is the first <classname>Step</classname> listed. If 'step A'
|
||||
completes normally, then 'step B' will execute, and so on. However, if
|
||||
'step A' fails, then the entire <classname>Job</classname> will fail and
|
||||
'step B' will not execute.</para>
|
||||
|
||||
<note>
|
||||
<para>With the Spring Batch namespace, the first step listed in the
|
||||
@@ -1100,17 +1100,17 @@
|
||||
<para>The next element specifies a pattern to match and the step to
|
||||
execute next:</para>
|
||||
|
||||
<para><programlisting>
|
||||
<job id="job">
|
||||
<step id="stepA">
|
||||
<next on="FAILED" to="stepB" />
|
||||
<next on="*" to="stepC" />
|
||||
</step>
|
||||
<step id="stepB" next="stepC" />
|
||||
<step id="stepC" />
|
||||
</job>
|
||||
<para><programlisting><![CDATA[
|
||||
<job id="job">
|
||||
<step id="stepA">
|
||||
<next on="FAILED" to="stepB" />
|
||||
<next on="*" to="stepC" />
|
||||
</step>
|
||||
<step id="stepB" next="stepC" />
|
||||
<step id="stepC" />
|
||||
</job>
|
||||
|
||||
</programlisting></para>
|
||||
]]></programlisting></para>
|
||||
|
||||
<para>The "on" attribute of a transition element uses a simple
|
||||
pattern-matching scheme to match the <classname>ExitStatus</classname>
|
||||
@@ -1152,16 +1152,16 @@
|
||||
<classname>StepExecution</classname> and is used by the framework to
|
||||
record the status of a <classname>Job</classname> or
|
||||
<classname>Step</classname>. It can be one of the following values:
|
||||
COMPLETED, STARTING, STARTED, FAILED, STOPPING, STOPPED, or UNKNOWN.
|
||||
Most of them are self explanatory: COMPLETED is the status set when a
|
||||
step or job has completed successfully, FAILED is set when it fails,
|
||||
and so on. The example above contains the following 'next'
|
||||
COMPLETED, STARTING, STARTED, STOPPING, STOPPED, FAILED, ABANDONED or
|
||||
UNKNOWN. Most of them are self explanatory: COMPLETED is the status
|
||||
set when a step or job has completed successfully, FAILED is set when
|
||||
it fails, and so on. The example above contains the following 'next'
|
||||
element:</para>
|
||||
|
||||
<programlisting>
|
||||
<next on="FAILED" to="stepB" />
|
||||
<programlisting><![CDATA[
|
||||
<next on="FAILED" to="stepB" />
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para>At first glance, it would appear that the 'on' attribute
|
||||
references the <classname>BatchStatus</classname> of the
|
||||
@@ -1178,14 +1178,14 @@
|
||||
code needs to be different? A good example comes from the skip sample
|
||||
job within the samples project:</para>
|
||||
|
||||
<programlisting>
|
||||
<step id="step1">
|
||||
<end on="FAILED" />
|
||||
<next on="COMPLETED WITH SKIPS" to="errorPrint1" />
|
||||
<next on="*" to="step2" />
|
||||
</step>
|
||||
<programlisting><![CDATA[
|
||||
<step id="step1">
|
||||
<end on="FAILED" />
|
||||
<next on="COMPLETED WITH SKIPS" to="errorPrint1" />
|
||||
<next on="*" to="step2" />
|
||||
</step>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para>The above step has three possibilities:</para>
|
||||
|
||||
@@ -1211,18 +1211,18 @@
|
||||
change the exit code based on the condition of the execution having
|
||||
skipped records:</para>
|
||||
|
||||
<programlisting> public class SkipCheckingListener extends StepExecutionListenerSupport {
|
||||
<programlisting><![CDATA[ public class SkipCheckingListener extends StepExecutionListenerSupport {
|
||||
|
||||
public ExitStatus afterStep(StepExecution stepExecution) {
|
||||
if (!stepExecution.getExitStatus().getExitCode().equals(ExitStatus.FAILED.getExitCode())
|
||||
&& stepExecution.getSkipCount() > 0) {
|
||||
&& stepExecution.getSkipCount() > 0) {
|
||||
return new ExitStatus("COMPLETED WITH SKIPS");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}</programlisting>
|
||||
}]]></programlisting>
|
||||
|
||||
<para>The above code is a <classname>StepExecutionListener</classname>
|
||||
that first checks to make sure the <classname>Step</classname> was
|
||||
@@ -1250,7 +1250,7 @@
|
||||
after the following step executes, the <classname>Job</classname> will
|
||||
end:</para>
|
||||
|
||||
<para><programlisting> <step id="stepC" /></programlisting></para>
|
||||
<para><programlisting><![CDATA[ <step id="stepC" />]]></programlisting></para>
|
||||
|
||||
<para>If no transitions are defined for a <classname>Step</classname>,
|
||||
then the <classname>Job</classname>'s statuses will be defined as
|
||||
@@ -1303,18 +1303,18 @@
|
||||
|
||||
<para>In the following scenario, if step2 fails, then the
|
||||
<classname>Job</classname> will stop with a
|
||||
<classname>BatchStatus</classname> of COMPLETE and an
|
||||
<classname>BatchStatus</classname> of COMPLETED and an
|
||||
<classname>ExitStatus</classname> of "COMPLETED" and step3 will not
|
||||
execute; otherwise, execution will move to step3. Additionally, if
|
||||
step2 fails, the <classname>Job</classname> will not be
|
||||
restartable.</para>
|
||||
execute; otherwise, execution will move to step3. Note that if step2
|
||||
fails, the <classname>Job</classname> will not be restartable (because
|
||||
the status is COMPLETED).</para>
|
||||
|
||||
<programlisting> <step id="step1" next="step2">
|
||||
<step id="step2">
|
||||
<end on="FAILED"/>
|
||||
<next on="*" to="step3"/>
|
||||
</step>
|
||||
<step id="step3"></programlisting>
|
||||
<programlisting><![CDATA[ <step id="step1" next="step2">
|
||||
<step id="step2">
|
||||
<end on="FAILED"/>
|
||||
<next on="*" to="step3"/>
|
||||
</step>
|
||||
<step id="step3">]]></programlisting>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
@@ -1338,33 +1338,33 @@
|
||||
Additionally, if step2 fails, and the <classname>Job</classname> is
|
||||
restarted, then execution will begin again on step2.</para>
|
||||
|
||||
<programlisting> <step id="step1" next="step2">
|
||||
<step id="step2">
|
||||
<fail on="FAILED" status="EARLY TERMINATION"/>
|
||||
<next on="*" to="step3"/>
|
||||
</step>
|
||||
<step id="step3"></programlisting>
|
||||
<programlisting><![CDATA[ <step id="step1" next="step2">
|
||||
<step id="step2">
|
||||
<fail on="FAILED" status="EARLY TERMINATION"/>
|
||||
<next on="*" to="step3"/>
|
||||
</step>
|
||||
<step id="step3">]]></programlisting>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>The 'Pause' Element</title>
|
||||
<title>The 'Stop' Element</title>
|
||||
|
||||
<para>The 'pause' element instructs a <classname>Job</classname> to
|
||||
stop with a <classname>BatchStatus</classname> of STOPPED. Pausing a
|
||||
<classname>Job</classname> is a meant to be a temporary break in
|
||||
processing so that the operator can take some action before restarting
|
||||
the <classname>Job</classname>. The 'pause' element requires a 'to'
|
||||
attribute that specifies the step where execution should pick up once
|
||||
the <classname>Job</classname>.</para>
|
||||
<para>The 'stop' element instructs a <classname>Job</classname> to
|
||||
stop with a <classname>BatchStatus</classname> of STOPPED. Stopping a
|
||||
<classname>Job</classname> can provide a temporary break in processing
|
||||
so that the operator can take some action before restarting the
|
||||
<classname>Job</classname>. The 'stop' element requires a 'restart'
|
||||
attribute that specifies the step where execution should pick up when
|
||||
the <classname>Job is restarted</classname>.</para>
|
||||
|
||||
<para>In the following scenario, if step1 finsihes with COMPLETE, then
|
||||
the job will then stop. Once it is restarted, execution will begin on
|
||||
step2.</para>
|
||||
|
||||
<para><programlisting> <step id="step1">
|
||||
<pause on="COMPLETED" to="step2"/>
|
||||
</step>
|
||||
<step id="step2"/></programlisting></para>
|
||||
<para><programlisting><![CDATA[ <step id="step1">
|
||||
<stop on="COMPLETED" restart="step2"/>
|
||||
</step>
|
||||
<step id="step2"/>]]></programlisting></para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -1377,7 +1377,7 @@
|
||||
<classname>JobExecutionDecider</classname> can be used to assist in the
|
||||
decision.</para>
|
||||
|
||||
<para><programlisting>
|
||||
<para><programlisting><![CDATA[
|
||||
public class MyDecider implements JobExecutionDecider {
|
||||
|
||||
public String decide(JobExecution jobExecution, StepExecution stepExecution) {
|
||||
@@ -1391,27 +1391,27 @@
|
||||
|
||||
}
|
||||
|
||||
</programlisting></para>
|
||||
]]></programlisting></para>
|
||||
|
||||
<para>In the job configuration, a "decision" tag will specify the
|
||||
decider to use as well as all of the transitions.</para>
|
||||
|
||||
<para><programlisting>
|
||||
<job id="job">
|
||||
<step id="step1" next="decision" />
|
||||
<para><programlisting><![CDATA[
|
||||
<job id="job">
|
||||
<step id="step1" next="decision" />
|
||||
|
||||
<decision id="skipCheckingDecision" decider="decider">
|
||||
<next on="FAILED" to="step2" />
|
||||
<next on="COMPLETED" to="step3" />
|
||||
</step>
|
||||
<decision id="skipCheckingDecision" decider="decider">
|
||||
<next on="FAILED" to="step2" />
|
||||
<next on="COMPLETED" to="step3" />
|
||||
</step>
|
||||
|
||||
<step id="step2" next="step3"/>
|
||||
<step id="step3" />
|
||||
</job>
|
||||
<step id="step2" next="step3"/>
|
||||
<step id="step3" />
|
||||
</job>
|
||||
|
||||
<bean id="decider" class="com.MyDecider"/>
|
||||
<bean id="decider" class="com.MyDecider"/>
|
||||
|
||||
</programlisting></para>
|
||||
]]></programlisting></para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
@@ -1428,16 +1428,16 @@
|
||||
elements such as the 'next' attribute or the 'next', 'end', 'fail', or
|
||||
'pause' elements.</para>
|
||||
|
||||
<programlisting> <split id="split1" next="step4">
|
||||
<flow>
|
||||
<step id="step1" next="step2"/>
|
||||
<step id="step2"/>
|
||||
</flow>
|
||||
<flow>
|
||||
<step id="step3"/>
|
||||
</flow>
|
||||
</split>
|
||||
<step id="step4"/></programlisting>
|
||||
<programlisting><![CDATA[ <split id="split1" next="step4">
|
||||
<flow>
|
||||
<step id="step1" next="step2"/>
|
||||
<step id="step2"/>
|
||||
</flow>
|
||||
<flow>
|
||||
<step id="step3"/>
|
||||
</flow>
|
||||
</split>
|
||||
<step id="step4"/>]]></programlisting>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -1451,14 +1451,14 @@
|
||||
Flat File resources can be configured using standard Spring
|
||||
constructs:</para>
|
||||
|
||||
<programlisting>
|
||||
<bean id="flatFileItemReader"
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource"
|
||||
value="file://outputs/20070122.testStream.CustomerReportStep.TEMP.txt" />
|
||||
</bean>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="flatFileItemReader"
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource"
|
||||
value="file://outputs/20070122.testStream.CustomerReportStep.TEMP.txt" />
|
||||
</bean>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para>The above <classname>Resource</classname> will load the file from
|
||||
the file system location specified. Note that absolute locations have to
|
||||
@@ -1468,13 +1468,13 @@
|
||||
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"
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource" value="${input.file.name}" />
|
||||
</bean>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="flatFileItemReader"
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource" value="${input.file.name}" />
|
||||
</bean>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para>All that would be required for this solution to work would be a
|
||||
system argument (-Dinput.file.name="file://file.txt"). (Note that although
|
||||
@@ -1490,34 +1490,34 @@
|
||||
accomplish this, Spring Batch allows for the late binding of various Job
|
||||
and Step attributes:</para>
|
||||
|
||||
<programlisting>
|
||||
<bean id="flatFileItemReader" scope="step"
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource" value="<emphasis role="bold">#{jobParameters[input.file.name]}</emphasis>" />
|
||||
</bean>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="flatFileItemReader" scope="step"
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource" value="]]><emphasis role="bold">#{jobParameters[input.file.name]}</emphasis><![CDATA[" />
|
||||
</bean>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para>Both the <classname>JobExecution</classname> and
|
||||
<classname>StepExecution</classname> level
|
||||
<classname>ExecutionContext</classname> can be accessed in the same
|
||||
way:</para>
|
||||
|
||||
<programlisting>
|
||||
<bean id="flatFileItemReader" scope="step"
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource" value="<emphasis role="bold">#{jobExecutionContext[input.file.name]}</emphasis>" />
|
||||
</bean>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="flatFileItemReader" scope="step"
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource" value="]]><emphasis role="bold">#{jobExecutionContext[input.file.name]}</emphasis><![CDATA[" />
|
||||
</bean>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<programlisting>
|
||||
<bean id="flatFileItemReader" scope="step"
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource" value="<emphasis role="bold">#{stepExecutionContext[input.file.name]}</emphasis>" />
|
||||
</bean>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="flatFileItemReader" scope="step"
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource" value="]]><emphasis role="bold">#{stepExecutionContext[input.file.name]}</emphasis><![CDATA[" />
|
||||
</bean>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<section>
|
||||
<title>Step Scope</title>
|
||||
@@ -1525,13 +1525,13 @@
|
||||
<para>All of the late binding examples from above have a scope of "step"
|
||||
declared on the bean definition:</para>
|
||||
|
||||
<programlisting>
|
||||
<bean id="flatFileItemReader" <emphasis role="bold">scope="step"</emphasis>
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource" value="#{jobParameters[input.file.name]}" />
|
||||
</bean>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="flatFileItemReader" ]]><emphasis role="bold">scope="step"</emphasis><![CDATA[
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource" value="#{jobParameters[input.file.name]}" />
|
||||
</bean>
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
|
||||
<para>Using a scope of <classname>Step</classname> is required in order
|
||||
to use late binding since the bean cannot actually be instantiated until
|
||||
@@ -1539,10 +1539,10 @@
|
||||
be found. Because it is not part of the Spring container by default, it
|
||||
must be added explicitly:</para>
|
||||
|
||||
<programlisting>
|
||||
<bean class="org.springframework.batch.core.scope.StepScope" />
|
||||
<programlisting><![CDATA[
|
||||
<bean class="org.springframework.batch.core.scope.StepScope" />
|
||||
|
||||
</programlisting>
|
||||
]]></programlisting>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
Reference in New Issue
Block a user