BATCH-1270: Update documentation for formatting consistency

This commit is contained in:
dhgarrette
2009-06-05 03:57:01 +00:00
parent 602230cd67
commit df2618d418
3 changed files with 662 additions and 889 deletions

View File

@@ -10,12 +10,12 @@
<mediaobject>
<imageobject role="html">
<imagedata align="center"
fileref="images/spring-batch-reference-model.png" scale="90" />
fileref="images/spring-batch-reference-model.png" scale="80" />
</imageobject>
<imageobject role="fo">
<imagedata align="center"
fileref="images/spring-batch-reference-model.png" scale="70"
fileref="images/spring-batch-reference-model.png" scale="40"
width="75%" />
</imageobject>
</mediaobject>
@@ -36,27 +36,21 @@
three required dependencies: a name, <classname>JobRepository</classname>,
and a list of <classname>Step</classname>s.</para>
<programlisting>
&lt;job id="footballJob"&gt;
<programlisting>&lt;job id="footballJob"&gt;
&lt;step id="playerload" parent="s1" next="gameLoad"/&gt;
&lt;step id="gameLoad" parent="s2" next="playerSummarization"/&gt;
&lt;step id="playerSummarization" parent="s3"/&gt;
&lt;/job&gt;
</programlisting>
&lt;/job&gt;</programlisting>
<para>The namespace defaults to referencing a repository with an id of
'jobRepository', which is a sensible default. However, this can be
overridden explicitly:</para>
<programlisting>
&lt;job id="footballJob" <emphasis role="bold">job-repository="specialRepository"</emphasis>&gt;
<programlisting>&lt;job id="footballJob" <emphasis role="bold">job-repository="specialRepository"</emphasis>&gt;
&lt;step id="playerload" parent="s1" next="gameLoad"/&gt;
&lt;step id="gameLoad" parent="s3" next="playerSummarization"/&gt;
&lt;step id="playerSummarization" parent="s3"/&gt;
&lt;/job&gt;
</programlisting>
&lt;/job&gt;</programlisting>
<section>
<title>Restartability</title>
@@ -74,38 +68,30 @@
be run as part of a new <classname>JobInstance</classname>, then the
restartable property may be set to 'false':</para>
<programlisting>
&lt;job id="footballJob" <emphasis role="bold">restartable="false"</emphasis>&gt;
&lt;step id="playerload" parent="s1" next="gameLoad"/&gt;
&lt;step id="gameLoad" parent="s2" next="playerSummarization"/&gt;
&lt;step id="playerSummarization" parent="s3"/&gt;
&lt;/job&gt;
</programlisting>
<programlisting>&lt;job id="footballJob" <emphasis role="bold">restartable="false"</emphasis>&gt;
...
&lt;/job&gt;</programlisting>
<para>To phrase it another way, setting restartable to false means "this
Job does not support being started again". Restarting a Job that is not
restartable will cause a <classname>JobRestartException</classname> to
be thrown:</para>
<programlisting>
Job job = new SimpleJob();
job.setRestartable(false);
<programlisting>Job job = new SimpleJob();
job.setRestartable(false);
JobParameters jobParameters = new JobParameters();
JobParameters jobParameters = new JobParameters();
JobExecution firstExecution = jobRepository.createJobExecution(job, jobParameters);
jobRepository.saveOrUpdate(firstExecution);
JobExecution firstExecution = jobRepository.createJobExecution(job, jobParameters);
jobRepository.saveOrUpdate(firstExecution);
try {
try {
jobRepository.createJobExecution(job, jobParameters);
fail();
}
catch (JobRestartException e) {
}
catch (JobRestartException e) {
// expected
}
</programlisting>
}</programlisting>
<para>This snippet of JUnit code shows how attempting to create a
<classname>JobExecution</classname> the first time for a non restartable
@@ -122,49 +108,40 @@
<classname>SimpleJob</classname> allows for this by calling a
<classname>JobListener</classname> at the appropriate time:</para>
<programlisting>
public interface JobExecutionListener {
<programlisting>public interface JobExecutionListener {
void beforeJob(JobExecution jobExecution);
void afterJob(JobExecution jobExecution);
}
</programlisting>
}</programlisting>
<para><classname>JobListener</classname>s can be added to a
<classname>SimpleJob</classname> via the listeners element on the
job:</para>
<programlisting>
&lt;job id="footballJob"&gt;
<programlisting>&lt;job id="footballJob"&gt;
&lt;step id="playerload" parent="s1" next="gameLoad"/&gt;
&lt;step id="gameLoad" parent="s2" next="playerSummarization"/&gt;
&lt;step id="playerSummarization" parent="s3"/&gt;
&lt;listeners&gt;
&lt;listener class="org.springframework.batch.sample.SampleListener"/&gt;
<emphasis role="bold"> &lt;listeners&gt;
&lt;listener class="org.springframework.batch.sample.SampleListener"/&gt;
&lt;/listeners&gt;
&lt;/job&gt;
</programlisting>
</emphasis>&lt;/job&gt;</programlisting>
<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){
<programlisting>public void afterJob(JobExecution jobExecution){
if( jobExecution.getStatus() == BatchStatus.COMPLETED ){
//job success
//job success
}
else if(jobExecution.getStatus() == BatchStatus.FAILED){
//job failure
//job failure
}
}
</programlisting>
}</programlisting>
<para>The annotations corresponding to this interface are:</para>
@@ -197,22 +174,19 @@
<classname>Job</classname> with two listeners and one
<classname>Step</classname>, "step1".</para>
<programlisting>
&lt;job id="baseJob" abstract="true"&gt;
<programlisting>&lt;job id="baseJob" abstract="true"&gt;
&lt;listeners&gt;
&lt;listener class="com.ListenerOne"/&gt;
&lt;listener class="com.ListenerOne"/&gt;
&lt;listeners&gt;
&lt;/job&gt;
&lt;/job&gt;
&lt;job id="job1" parent="baseJob3"&gt;
&lt;job id="job1" parent="baseJob3"&gt;
&lt;step id="step1" parent="standaloneStep"/&gt;
&lt;listeners merge="true"&gt;
&lt;listener class="com.ListenerTwo"/&gt;
&lt;listener class="com.ListenerTwo"/&gt;
&lt;listeners&gt;
&lt;/job&gt;
</programlisting>
&lt;/job&gt;</programlisting>
<para>Please see the section on <link
linkend="InheritingFromParentStep">Inheriting from a Parent Step</link>
@@ -262,15 +236,12 @@
collaborators. However, there are still a few configuration options
available:</para>
<programlisting>
&lt;job-repository id="jobRepository"
<programlisting>&lt;job-repository id="jobRepository"
dataSource="dataSource"
transactionManager="transactionManager"
isolation-level-for-create="serializable"
table-prefix="BATCH_"
/&gt;
</programlisting>
/&gt;</programlisting>
<para>None of the configuration options listed above are required except
the id. If they are not set, the defaults shown above will be used. They
@@ -295,30 +266,24 @@
that the SERIALIZED will cause problems, as long as the database
platform supports it. However, this can be overridden:</para>
<para><programlisting>
&lt;job-repository id="jobRepository"
<emphasis role="bold">isolation-level-for-create="ISOLATION_REPEATABLE_READ" /&gt;</emphasis>
</programlisting></para>
<para><programlisting>&lt;job-repository id="jobRepository"
<emphasis role="bold">isolation-level-for-create="ISOLATION_REPEATABLE_READ"</emphasis> /&gt;</programlisting></para>
<para>If the namespace or factory beans aren't used then it is also
essential to configure the transactional behavior of the repository
using AOP:</para>
<para><programlisting>
&lt;aop:config&gt;
&lt;aop:advisor
pointcut="execution(* org.springframework.batch.core..*Repository+.*(..))"
&lt;advice-ref="txAdvice" /&gt;
&lt;/aop:config&gt;
<para><programlisting>&lt;aop:config&gt;
&lt;aop:advisor
pointcut="execution(* org.springframework.batch.core..*Repository+.*(..))"/&gt;
&lt;advice-ref="txAdvice" /&gt;
&lt;/aop:config&gt;
&lt;tx:advice id="txAdvice" transaction-manager="transactionManager"&gt;
&lt;tx:attributes&gt;
&lt;tx:method name="*" /&gt;
&lt;/tx:attributes&gt;
&lt;/tx:advice&gt;
</programlisting></para>
&lt;tx:advice id="txAdvice" transaction-manager="transactionManager"&gt;
&lt;tx:attributes&gt;
&lt;tx:method name="*" /&gt;
&lt;/tx:attributes&gt;
&lt;/tx:advice&gt;</programlisting></para>
<para>This fragment can be used as is, with almost no changes. Remember
also to include the appropriate namespace declarations and to make sure
@@ -338,12 +303,8 @@
meta data tables is needed within the same schema, then the table prefix
will need to be changed:</para>
<programlisting>
&lt;job-repository id="jobRepository"
<emphasis role="bold">table-prefix="SYSTEM.TEST_"</emphasis>
/&gt;
</programlisting>
<programlisting>&lt;job-repository id="jobRepository"
<emphasis role="bold">table-prefix="SYSTEM.TEST_"</emphasis> /&gt;</programlisting>
<para>Given the above changes, every query to the meta data tables will
be prefixed with "SYSTEM.TEST_". BATCH_JOB_EXECUTION will be referred to
@@ -363,13 +324,12 @@
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. For
this reason, Spring batch provides an in-memory Map version of the job
respository:</para>
repository:</para>
<programlisting><![CDATA[<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
</bean>
]]></programlisting>
<programlisting>&lt;bean id="jobRepository"
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"&gt;
&lt;property name="transactionManager" ref="transactionManager"/&gt;
&lt;/bean&gt;</programlisting>
<para>Note that the in-memory repository is volatile and so does not
allow restart between JVM instances. It also cannot guarantee that two
@@ -377,14 +337,11 @@
use the database version of the repository wherever you need quality of
service.</para>
<para>However it does require a transaction manager to be
defined because there are rollback semantics within the
repository, and because the business logic might still be
transactional (e.g. RDBMS access). For testing purposes many
people find
the <classname>ResourcelessTransactionManager</classname>
useful.</para>
<para>However it does require a transaction manager to be defined
because there are rollback semantics within the repository, and because
the business logic might still be transactional (e.g. RDBMS access). For
testing purposes many people find the
<classname>ResourcelessTransactionManager</classname> useful.</para>
</section>
<section>
@@ -397,12 +354,10 @@
shortcut and use it to set the database type to the closest
match:</para>
<programlisting>
&lt;bean id="jobRepository" class="org...JobRepositoryFactoryBean"&gt;
&lt;property name="databaseType" value="db2"/&gt;
&lt;property name="dataSource" ref="dataSource"/&gt;
&lt;/bean&gt;
</programlisting>
<programlisting>&lt;bean id="jobRepository" class="org...JobRepositoryFactoryBean"&gt;
&lt;property name="databaseType" value="db2"/&gt;
&lt;property name="dataSource" ref="dataSource"/&gt;
&lt;/bean&gt;</programlisting>
<para>(The <classname>JobRepositoryFactoryBean</classname> tries to
auto-detect the database type from the <classname>DataSource</classname>
@@ -428,10 +383,10 @@
a <classname>JobRepository</classname>, in order to obtain an
execution:</para>
<programlisting> &lt;bean id="jobLauncher"
class="org.springframework.batch.execution.launch.SimpleJobLauncher"&gt;
<programlisting>&lt;bean id="jobLauncher"
class="org.springframework.batch.execution.launch.SimpleJobLauncher"&gt;
&lt;property name="jobRepository" ref="jobRepository" /&gt;
&lt;/bean&gt;</programlisting>
&lt;/bean&gt;</programlisting>
<para>Once a <link
linkend="jobExecution"><classname>JobExecution</classname></link> is
@@ -479,13 +434,13 @@
configured to allow for this scenario by configuring a
<classname>TaskExecutor</classname>:</para>
<programlisting> &lt;bean id="jobLauncher"
class="org.springframework.batch.execution.launch.SimpleJobLauncher"&gt;
<programlisting>&lt;bean id="jobLauncher"
class="org.springframework.batch.execution.launch.SimpleJobLauncher"&gt;
&lt;property name="jobRepository" ref="jobRepository" /&gt;
&lt;property name="taskExecutor"&gt;
&lt;bean class="org.springframework.core.task.SimpleAsyncTaskExecutor" /&gt;
&lt;bean class="org.springframework.core.task.SimpleAsyncTaskExecutor" /&gt;
&lt;/property&gt;
&lt;/bean&gt;</programlisting>
&lt;/bean&gt;</programlisting>
<para>Any implementation of the spring <classname>TaskExecutor</classname>
interface can be used to control how jobs are asynchronously
@@ -594,16 +549,13 @@
will be converted into <classname>JobParameters</classname>. An
example of the XML configuration is below:</para>
<programlisting> &lt;job id="endOfDay"&gt;
&lt;steps&gt;
&lt;step id="step1" parent="simpleStep" /&gt;
&lt;!-- Step details removed for clarity --&gt;
&lt;/steps&gt;
&lt;/job&gt;
<programlisting>&lt;job id="endOfDay"&gt;
&lt;step id="step1" parent="simpleStep" /&gt;
&lt;/job&gt;
&lt;!-- Launcher details removed for clarity --&gt;
&lt;beans: bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher" /&gt;</programlisting>
&lt;!-- Launcher details removed for clarity --&gt;
&lt;beans:bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher" /&gt;</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
@@ -641,9 +593,10 @@
to a number using the <classname>ExitCodeMapper</classname>
interface:</para>
<programlisting> public interface ExitCodeMapper {
<programlisting>public interface ExitCodeMapper {
public int intValue(String exitCode);
}</programlisting>
<para>The essential contract of an
@@ -703,9 +656,8 @@
is required when handling an <classname>HttpRequest</classname>. An
example is below:</para>
<programlisting>
@Controller
public class JobLauncherController {
<programlisting>@Controller
public class JobLauncherController {
@Autowired
JobLauncher jobLauncher;
@@ -715,11 +667,9 @@
@RequestMapping("/jobLauncher.html")
public void handle() throws Exception{
jobLauncher.run(job, new JobParameters());
jobLauncher.run(job, new JobParameters());
}
}
</programlisting>
}</programlisting>
</section>
</section>
@@ -776,8 +726,7 @@
query the repository for existing executions. This functionality is
provided by the <classname>JobExplorer</classname> interface:</para>
<programlisting>
public interface JobExplorer {
<programlisting>public interface JobExplorer {
List&lt;JobInstance&gt; getJobInstances(String jobName, int start, int count);
@@ -790,9 +739,7 @@
List&lt;JobExecution&gt; getJobExecutions(JobInstance jobInstance);
Set&lt;JobExecution&gt; findRunningJobExecutions(String jobName);
}
</programlisting>
}</programlisting>
<para>As is evident from the method signatures above,
<classname>JobExplorer</classname> is a read-only version of the
@@ -800,11 +747,8 @@
<classname>JobRepository</classname>, it can be easily configured via a
factory bean:</para>
<programlisting>
&lt;bean id="jobExplorer" class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean"
p:dataSource-ref="dataSource" /&gt;
</programlisting>
<programlisting>&lt;bean id="jobExplorer" class="org.spr...JobExplorerFactoryBean"
p:dataSource-ref="dataSource" /&gt;</programlisting>
<para><link linkend="repositoryTablePrefix">Earlier in this
chapter</link>, it was mentioned that the table prefix of the
@@ -813,11 +757,8 @@
<classname>JobExplorer</classname> is working with the same tables, it
too needs the ability to set a prefix:</para>
<programlisting>
&lt;bean id="jobExplorer" class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean"
p:dataSource-ref="dataSource" <emphasis role="bold">p:tablePrefix="BATCH_" </emphasis>/&gt;
</programlisting>
<programlisting>&lt;bean id="jobExplorer" class="org.spr...JobExplorerFactoryBean"
p:dataSource-ref="dataSource" <emphasis role="bold">p:tablePrefix="BATCH_" </emphasis>/&gt;</programlisting>
</section>
<section>
@@ -832,39 +773,39 @@
provides for these types of operations via the
<classname>JobOperator</classname> interface:</para>
<programlisting>
public interface JobOperator {
<programlisting>public interface JobOperator {
List&lt;Long&gt; getExecutions(long instanceId) throws NoSuchJobInstanceException;
List&lt;Long&gt; getJobInstances(String jobName, int start, int count) throws NoSuchJobException;
List&lt;Long&gt; getJobInstances(String jobName, int start, int count)
throws NoSuchJobException;
Set&lt;Long&gt; getRunningExecutions(String jobName) throws NoSuchJobException;
String getParameters(long executionId) throws NoSuchJobExecutionException;
Long start(String jobName, String parameters)
throws NoSuchJobException, JobInstanceAlreadyExistsException;
throws NoSuchJobException, JobInstanceAlreadyExistsException;
Long restart(long executionId)
throws JobInstanceAlreadyCompleteException, NoSuchJobExecutionException,
throws JobInstanceAlreadyCompleteException, NoSuchJobExecutionException,
NoSuchJobException, JobRestartException;
Long startNextInstance(String jobName)
throws NoSuchJobException, JobParametersNotFoundException, JobRestartException,
JobExecutionAlreadyRunningException, JobInstanceAlreadyCompleteException;
throws NoSuchJobException, JobParametersNotFoundException, JobRestartException,
JobExecutionAlreadyRunningException, JobInstanceAlreadyCompleteException;
boolean stop(long executionId) throws NoSuchJobExecutionException, JobExecutionNotRunningException;
boolean stop(long executionId)
throws NoSuchJobExecutionException, JobExecutionNotRunningException;
String getSummary(long executionId) throws NoSuchJobExecutionException;
Map&lt;Long, String&gt; getStepExecutionSummaries(long executionId) throws NoSuchJobExecutionException;
Map&lt;Long, String&gt; getStepExecutionSummaries(long executionId)
throws NoSuchJobExecutionException;
Set&lt;String&gt; getJobNames();
}
</programlisting>
}</programlisting>
<para>The above operations represent methods from many different
interfaces, such as <classname>JobLauncher</classname>,
@@ -874,19 +815,16 @@
implementation of <classname>JobOperator</classname>,
<classname>SimpleJobOperator</classname>, has many dependencies:</para>
<programlisting>
&lt;bean id="jobOperator" class="org.springframework.batch.core.launch.support.SimpleJobOperator"&gt;
<programlisting>&lt;bean id="jobOperator" class="org.spr...SimpleJobOperator"&gt;
&lt;property name="jobExplorer"&gt;
&lt;bean class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean"&gt;
&lt;property name="dataSource" ref="dataSource" /&gt;
&lt;/bean&gt;
&lt;bean class="org.spr...JobExplorerFactoryBean"&gt;
&lt;property name="dataSource" ref="dataSource" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="jobRepository" ref="jobRepository" /&gt;
&lt;property name="jobRegistry" ref="jobRegistry" /&gt;
&lt;property name="jobLauncher" ref="jobLauncher" /&gt;
&lt;/bean&gt;
</programlisting>
&lt;/bean&gt;</programlisting>
</section>
<section>
@@ -911,14 +849,11 @@
<classname>Job</classname> to force the <classname>Job</classname> to a
new instance:</para>
<programlisting>
public interface JobParametersIncrementer {
<programlisting>public interface JobParametersIncrementer {
JobParameters getNext(JobParameters parameters);
}
</programlisting>
}</programlisting>
<para>The contract of <classname>JobParametersIncrementer</classname> is
that, given a <link
@@ -934,19 +869,16 @@
numerical values that help to identify the <classname>Job</classname>,
as shown below:</para>
<programlisting>
public class SampleIncrementer implements JobParametersIncrementer {
<programlisting>public class SampleIncrementer implements JobParametersIncrementer {
public JobParameters getNext(JobParameters parameters) {
if (parameters==null || parameters.isEmpty()) {
return new JobParametersBuilder().addLong("run.id", 1L).toJobParameters();
}
long id = parameters.getLong("run.id",1L) + 1;
return new JobParametersBuilder().addLong("run.id", id).toJobParameters();
if (parameters==null || parameters.isEmpty()) {
return new JobParametersBuilder().addLong("run.id", 1L).toJobParameters();
}
long id = parameters.getLong("run.id",1L) + 1;
return new JobParametersBuilder().addLong("run.id", id).toJobParameters();
}
}
</programlisting>
}</programlisting>
<para>In this example, the value with a key of 'run.id' is used to
discriminate between <classname>JobInstances</classname>. If the
@@ -957,14 +889,9 @@
be associated with <classname>Job</classname> via the 'incrementer'
attribute in the namespace:</para>
<programlisting>
&lt;job id="footballJob" <emphasis role="bold">incrementer="sampleIncrementer"</emphasis>&gt;
&lt;step id="playerload" parent="s1" next="gameLoad"/&gt;
&lt;step id="gameLoad" parent="s2" next="playerSummarization"/&gt;
&lt;step id="playerSummarization" parent="s3"/&gt;
&lt;/job&gt;
</programlisting>
<programlisting>&lt;job id="footballJob" <emphasis role="bold">incrementer="sampleIncrementer"</emphasis>&gt;
...
&lt;/job&gt;</programlisting>
</section>
<section>
@@ -974,11 +901,8 @@
<classname>JobOperator</classname> is gracefully stopping a
<classname>Job:</classname></para>
<programlisting>
Set&lt;Long&gt; executions = jobOperator.getRunningExecutions("sampleJob");
jobOperator.stop(executions.iterator().next());
</programlisting>
<programlisting>Set&lt;Long&gt; executions = jobOperator.getRunningExecutions("sampleJob");
jobOperator.stop(executions.iterator().next()); </programlisting>
<para>The shutdown is not immediate, since there is no way to force
immediate shutdown, especially if the execution is currently in

File diff suppressed because it is too large Load Diff

View File

@@ -19,12 +19,11 @@
<mediaobject>
<imageobject role="html">
<imagedata align="center" fileref="images/step.png" scale="75" width="" />
<imagedata align="center" fileref="images/step.png" scale="50" />
</imageobject>
<imageobject role="fo">
<imagedata align="center" contentwidth="480" fileref="images/step.png"
scale="50" width="75%" />
<imagedata align="center" fileref="images/step.png" scale="30" />
</imageobject>
</mediaobject>
@@ -43,13 +42,12 @@
<mediaobject>
<imageobject role="html">
<imagedata align="center"
fileref="images/chunk-oriented-processing.png" scale="75"
width="" />
fileref="images/chunk-oriented-processing.png" scale="75" />
</imageobject>
<imageobject role="fo">
<imagedata align="center"
fileref="images/chunk-oriented-processing.png" width="75%" />
fileref="images/chunk-oriented-processing.png" scale="75" />
</imageobject>
</mediaobject>
@@ -477,8 +475,8 @@ itemWriter.write(items);</programlisting>
records are logged as well, which will be covered later when discussing
listeners.<programlisting>&lt;step id="step1"&gt;
&lt;tasklet&gt;
&lt;chunk reader="flatFileItemReader" writer="itemWriter" commit-interval="10" <emphasis
role="bold">skip-limit="10"</emphasis>&gt;
&lt;chunk reader="flatFileItemReader" writer="itemWriter"
commit-interval="10" <emphasis role="bold">skip-limit="10"</emphasis>&gt;
<emphasis role="bold">&lt;skippable-exception-classes&gt;
org.springframework.batch.item.file.FlatFileParseException
&lt;/skippable-exception-classes&gt;</emphasis>
@@ -505,8 +503,8 @@ itemWriter.write(items);</programlisting>
identify which exceptions should cause failure and skip everything
else:<programlisting>&lt;step id="step1"&gt;
&lt;tasklet&gt;
&lt;chunk reader="flatFileItemReader" writer="itemWriter" commit-interval="10" <emphasis
role="bold">skip-limit="10"</emphasis>&gt;
&lt;chunk reader="flatFileItemReader" writer="itemWriter"
commit-interval="10" <emphasis role="bold">skip-limit="10"</emphasis>&gt;
<emphasis role="bold"> &lt;skippable-exception-classes&gt;
java.lang.Exception
&lt;/skippable-exception-classes&gt;
@@ -539,8 +537,8 @@ itemWriter.write(items);</programlisting>
<programlisting>&lt;step id="step1"&gt;
&lt;tasklet&gt;
&lt;chunk reader="itemReader" writer="itemWriter" commit-interval="2" <emphasis
role="bold">retry-limit="3"</emphasis>&gt;
&lt;chunk reader="itemReader" writer="itemWriter"
commit-interval="2" <emphasis role="bold">retry-limit="3"</emphasis>&gt;
<emphasis role="bold">&lt;retryable-exception-classes&gt;
org.springframework.dao.DeadlockLoserDataAccessException
&lt;/retryable-exception-classes&gt;</emphasis>
@@ -612,7 +610,9 @@ itemWriter.write(items);</programlisting>
<programlisting>&lt;step id="step1"&gt;
&lt;tasklet&gt;
&lt;chunk reader="itemReader" writer="itemWriter" commit-interval="2"/&gt;
&lt;transaction-attributes isolation="DEFAULT" propagation="REQUIRED" timeout="30"/&gt;
&lt;transaction-attributes isolation="DEFAULT"
propagation="REQUIRED"
timeout="30"/&gt;
&lt;/tasklet&gt;
&lt;/step&gt;</programlisting>
</section>
@@ -1115,12 +1115,12 @@ itemWriter.write(items);</programlisting>
<mediaobject>
<imageobject role="html">
<imagedata align="center" fileref="images/sequential-flow.png"
scale="80" width="40%" />
scale="80" />
</imageobject>
<imageobject role="fo">
<imagedata align="center" fileref="images/sequential-flow.png"
width="40%" />
scale="40" />
</imageobject>
</mediaobject>
@@ -1298,8 +1298,9 @@ itemWriter.write(items);</programlisting>
<programlisting>public class SkipCheckingListener extends StepExecutionListenerSupport {
public ExitStatus afterStep(StepExecution stepExecution) {
if (!stepExecution.getExitStatus().getExitCode().equals(ExitStatus.FAILED.getExitCode())
&amp;&amp; stepExecution.getSkipCount() &gt; 0) {
String exitCode = stepExecution.getExitStatus().getExitCode();
if (!exitCode.equals(ExitStatus.FAILED.getExitCode()) &amp;&amp;
stepExecution.getSkipCount() &gt; 0) {
return new ExitStatus("COMPLETED WITH SKIPS");
}
else {