(1) Finally fixed glossary so that it would generate with mvn site. We moved it to a glossary instead of chapter and added it back into index.xml. Previously it was commented out.

(2) Added appendix and moved the table of available item readers into the appendix.
(3) Grepped for all <programlisting> elements and untabified the regions so that they looked better. 
(4) Reordering of chapters was done earlier in conjunction with Lucas.
This commit is contained in:
wxlund
2008-03-06 01:50:41 +00:00
parent 6c77820214
commit 1ead5462e0
7 changed files with 467 additions and 419 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -5,8 +5,137 @@
<title>List of ItemReaders</title>
<section>
<title></title>
<title>Item Readers</title>
<table>
<title>Available Item Readers</title>
<para></para>
<tgroup cols="3">
<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>
<tbody>
<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>
<row>
<entry align="left">ValidatingItemReader</entry>
<entry align="left">java.lang.Object</entry>
<entry align="left">A simple extension of DelegatingItemReader
that provides for validation before returning input.</entry>
</row>
<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
mark the beginning and end of records with the constant values in
FieldSetMapper AggregateItemReader#<emphasis
role="bold">BEGIN_RECORD</emphasis> and
AggregateItemReader#<emphasis
role="bold">END_RECORD</emphasis></entry>
</row>
<row>
<entry align="left">DelegatingItemReader</entry>
<entry align="left">java.lang.Object</entry>
<entry align="left">Extends AbstractMethodInvokingDelegator, which
enables dynamically calling of a custom method of the injected
object. Provides a convenient API for dynamic method invocation
shielding subclasses from the low-level details and exception
handling.</entry>
</row>
<row>
<entry align="left">FlatFileItemReader</entry>
<entry align="left">java.lang.String</entry>
<entry align="left">Reads from a flat file, includes ItemStream
and Skippable functionality. See section on Read from a
File</entry>
</row>
<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>
<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">java.lang.Object</entry>
<entry align="left">Reads via iBATIS based on a driving query. 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()
method</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</appendix>
</appendix>

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glossary PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<glossary>
<glossdiv>
<title></title>
<glossentry>
<glossterm></glossterm>
<glossdef>
<para></para>
</glossdef>
</glossentry>
</glossdiv>
</glossary>

View File

@@ -1,72 +1,96 @@
<?xml version='1.0'?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd">
<chapter id="glossary">
<title>Glossary</title>
<section>
<title>Glossary Items</title>
<para></para>
<orderedlist numeration="arabic">
<listitem>
<para><emphasis role="bold">Batch</emphasis>: An accumulation of
business transactions over time.</para>
</listitem>
<listitem>
<para><emphasis role="bold">Batch Application Style</emphasis>:
Term used to designate batch as an application style in its own
right similar to online, Web or SOA. It has standard elements of
input, validation, transformation of information to business
model, business processing and output. In addition, it requires
monitoring at a macro level.</para>
</listitem>
<listitem>
<para><emphasis role="bold">Batch Processing</emphasis>: The
handling of a batch of many business transactions that have
accumulated over a period of time (e.g. an hour, day, week,
month, or year). It is the application of a process, or set of
processes, to many data entities or objects in a repetitive and
predictable fashion with either no manual element, or a separate
manual element for error processing.</para>
</listitem>
<listitem>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glossary PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<glossary>
<glossdiv>
<title>Spring Batch Glossary</title>
<para><emphasis role="bold">Batch Window</emphasis>: The time
frame within which a batch job must complete. This can be
constrained by other systems coming online, other dependent jobs
needing to execute or other factors specific to the batch
environment.</para>
<glossentry>
<glossterm>Batch</glossterm>
<glossdef>
<para>An accumulation of business transactions over
time.
</para>
</glossdef>
</glossentry>
</listitem>
<glossentry>
<glossterm>Batch Application Style</glossterm>
<glossdef>
<para>
Term used to designate batch as an application style in its
own right similar to online, Web or SOA. It has standard
elements of input, validation, transformation of
information to business model, business processing and
output. In addition, it requires monitoring at a macro
level.
</para>
</glossdef>
</glossentry>
<listitem>
<glossentry>
<glossterm>Batch Processing</glossterm>
<glossdef>
<para>
The handling of a batch of many business transactions that
have accumulated over a period of time (e.g. an hour, day,
week, month, or year). It is the application of a process,
or set of processes, to many data entities or objects in a
repetitive and predictable fashion with either no manual
element, or a separate manual element for error processing.
</para>
</glossdef>
</glossentry>
<para><emphasis role="bold">Step Controller</emphasis>: It is the
main batch task or Unit of Work controller. It initializes the
tasklet, and controls the transaction environment based on commit
interval setting, etc.</para>
<glossentry>
<glossterm>Batch Window</glossterm>
<glossdef>
<para>
The time frame within which a batch job must complete. This
can be constrained by other systems coming online, other
dependent jobs needing to execute or other factors specific
to the batch environment.
</para>
</glossdef>
</glossentry>
</listitem>
<glossentry>
<glossterm>Step Controller</glossterm>
<glossdef>
<para>
It is the main batch task or Unit of Work controller. It
initializes the tasklet, and controls the transaction
environment based on commit interval setting, etc.
</para>
</glossdef>
</glossentry>
<listitem>
<glossentry>
<glossterm>Tasklet</glossterm>
<glossdef>
<para>
The main application program created by application developer to process
the business logic for each LUW.
</para>
</glossdef>
</glossentry>
<para><emphasis role="bold">Tasklet</emphasis>: The main
application program created by application developer to process
the business logic for each LUW.</para>
<glossentry>
<glossterm>Batch Job Type</glossterm>
<glossdef>
<para>
Job Types describe application of jobs for particular type
of processing. Common areas are interface processing
(typically flat files), forms processing (either for online
pdf generation or print formats), report processing.
</para>
</glossdef>
</glossentry>
</listitem>
<listitem>
<para><emphasis role="bold">Batch Job Type</emphasis>: Job Types
describe application of jobs for particular type of processing.
Common areas are interface processing (typically flat files),
forms processing (either for online pdf generation or print
formats), report processing. s</para>
</listitem>
<listitem>
<para><emphasis role="bold">Driving Query</emphasis>: A driving
<glossentry>
<glossterm>Driving Query</glossterm>
<glossdef>
<para>A driving
query identifies the set of work for a job to do; the job then
breaks that work into individual units of work. For instance,
identify all financial transactions that have a status of
@@ -75,110 +99,151 @@
each record ID then becomes a unit of work. A driving query may
involve a join (if the criteria for selection falls across two or
more tables) or it may work with a single table.</para>
</glossdef>
</listitem>
</glossentry>
<listitem>
<glossentry>
<para><emphasis role="bold">Logicial Unit of Work
(LUW)</emphasis>: A batch job iterates through a driving query
<glossterm>Logicial Unit of Work
(LUW)</glossterm>
<glossdef>
<para>A batch job iterates through a driving query
(or another input source such as a file) to perform the set of
work that the job must accomplish. Each iteration of work
performed is a unit of work.</para>
</glossdef>
</listitem>
</glossentry>
<listitem>
<glossentry>
<para><emphasis role="bold">Commit Interval</emphasis>: A set of
<glossterm>Commit Interval</glossterm>
<glossdef>
<para>A set of
LUWs constitute a commit interval.</para>
</glossdef>
</listitem>
</glossentry>
<listitem>
<glossentry>
<para><emphasis role="bold">Partitioning</emphasis>: Splitting a
<glossterm>Partitioning</glossterm>
<glossdef>
<para>Splitting a
job into multiple threads where each thread is responsible for a
subset of the overall data to be processed. The threads of
execution may be within the same JVM or they may span JVMs in a
clustered environment that supports workload balancing.</para>
</glossdef>
</listitem>
</glossentry>
<listitem>
<glossentry>
<para><emphasis role="bold">Staging Table</emphasis>: A table
<glossterm>Staging Table</glossterm>
<glossdef>
<para>A table
that holds temporary data while it is being processed.</para>
</glossdef>
</listitem>
</glossentry>
<listitem>
<glossentry>
<para><emphasis role="bold">Restartable</emphasis>: - a job that
<glossterm>Restartable</glossterm>
<glossdef>
<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>
</listitem>
</glossentry>
<listitem>
<glossentry>
<para><emphasis role="bold">Rerunnable</emphasis> - a job that is restartable and manages it&apos;s own state in terms of previous run&apos;s record
processing. Note&gt;&gt;: Rerunnable is tied to the driving query. If the driving query can be formed so that it will limit the
processed rows when the job is restarted than re-runnable = true. This is managed by the application architecture. Often times a
condition is added to the where statement to limit the rows returned by the driving query with something like &quot;and
processedFlag != true&quot;.</para>
<glossterm>Rerunnable</glossterm>
<glossdef>
<para>
a job that is restartable and manages it&apos;s own state in
terms of previous run&apos;s record processing. Note&gt;&gt;
Rerunnable is tied to the driving query. If the driving
query can be formed so that it will limit the processed rows
when the job is restarted than re-runnable = true. This is
managed by the application architecture. Often times a
condition is added to the where statement to limit the rows
returned by the driving query with something like &quot;and
processedFlag != true&quot;.
<note>
<title>Understanding Rerunnable</title>
<para>
If re-runnable = false the architecture assumes responsibility for
tracking which rows have been processed. There is a default strategy
for tracking the last record processed by partition. Most batch jobs
only have one partition. The option is only valid for a restartable
job. The reason being is that the architecture will have to persist
the restart data, which is only available on a restartable job as the
restart data is saved and made available from the execution of the
last run if restartable = true. In pseudo code it is the following:
</para>
<para>
StartOver ::= restartable = false. Restartable ::= true | false If
(Restartable) re-runnable ::= true | false We don't persist restart
information for a non-restartable job. As you can see, it doesn't
make sense. Rerunnable has always confused the best of us and we're
open to suggestions on how to better explain it.
</para>
</note>
</para>
</glossdef>
<programlisting><![CDATA[
Note: If re-runnable = false the architecture assumes responsibility for tracking which rows have been processed. There is a default strategy
for tracking the last record processed by partition. Most batch jobs only have one partition. The option is only valid for a restartable job.
The reason being is that the architecture will have to persist the restart data, which is only available on a restartable job as the restart data is
saved and made available from the execution of the last run if restartable = true.
In pseudo code it is the following:
StartOver ::= restartable = false. Restartable ::= true | false
If (Restartable)
re-runnable ::= true | false
We don't persist restart information for a non-restartable job. As you can see, it doesn't make sense. Rerunnable has always confused the best
of us and we're open to suggestions on how to better explain it.
]]></programlisting>
</listitem>
</glossentry>
<listitem>
<glossentry>
<para><emphasis role="bold">Repeat</emphasis>: One of the most basic units of batch processing, that defines repeatability calling a
portion of code until it is finished, and while there is no error. Typically a batch process would be repeatable as long as there is input.
</para>
<glossterm>Repeat</glossterm>
<glossdef>
<para>One of the most basic units of batch processing, that
defines repeatability calling a portion of code until it is
finished, and while there is no error. Typically a batch
process would be repeatable as long as there is input.
</para>
</glossdef>
</glossentry>
<glossentry>
</listitem>
<listitem>
<para><emphasis role="bold">Retry</emphasis>: Simplifies the execution of operations with retry semantics most frequently associated
<glossterm>Retry</glossterm>
<glossdef>
<para>Simplifies the execution of operations with retry semantics most frequently associated
with handling transactional output exceptions. Retry is slightly different from repeat, rather than continually 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>
</glossdef>
</listitem>
</glossentry>
<listitem>
<glossentry>
<para><emphasis role="bold">Recover</emphasis>: Recover operations handle an exception in such a way that a repeat process is able to
<glossterm>Recover</glossterm>
<glossdef>
<para>Recover operations handle an exception in such a way that a repeat process is able to
continue.
</para>
</glossdef>
</listitem>
<listitem>
</glossentry>
<glossentry>
<para><emphasis role="bold">Skip</emphasis>: Skip is a recovery strategy often used on file input sources as the strategy for ignoring
<glossterm>Skip</glossterm>
<glossdef>
<para>Skip is a recovery strategy often used on file input sources as the strategy for ignoring
bad input records that failed validation.
</para>
</glossdef>
</listitem>
</orderedlist>
</section>
</chapter>
</glossentry>
</glossdiv>
</glossary>

View File

@@ -37,6 +37,7 @@
<xi:include href="samples.xml"/>
<xi:include href="batch-job-testing.xml"/>
<xi:include href="batch-performance-testing.xml"/>
<!-- <xi:include href="glossary.xml"/> -->
<xi:include href="appendix.xml"/>
<xi:include href="glossary.xml"/>
</book>

View File

@@ -86,139 +86,8 @@
role="bold">ItemReader</emphasis>s are the means for providing data from
many different types of input sources. The table provide below list an
inventory of ItemReaders currently available. In addition it is easy to
create a custom ItemReader.</para>
<table>
<title></title>
<tgroup cols="3">
<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>
<tbody>
<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>
<row>
<entry align="left">ValidatingItemReader</entry>
<entry align="left">java.lang.Object</entry>
<entry align="left">A simple extension of DelegatingItemReader
that provides for validation before returning input.</entry>
</row>
<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
mark the beginning and end of records with the constant values in
FieldSetMapper AggregateItemReader#<emphasis
role="bold">BEGIN_RECORD</emphasis> and
AggregateItemReader#<emphasis
role="bold">END_RECORD</emphasis></entry>
</row>
<row>
<entry align="left">DelegatingItemReader</entry>
<entry align="left">java.lang.Object</entry>
<entry align="left">Extends AbstractMethodInvokingDelegator, which
enables dynamically calling of a custom method of the injected
object. Provides a convenient API for dynamic method invocation
shielding subclasses from the low-level details and exception
handling.</entry>
</row>
<row>
<entry align="left">FlatFileItemReader</entry>
<entry align="left">java.lang.String</entry>
<entry align="left">Reads from a flat file, includes ItemStream
and Skippable functionality. See section on Read from a
File</entry>
</row>
<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>
<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">java.lang.Object</entry>
<entry align="left">Reads via iBATIS based on a driving query. 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()
method</entry>
</row>
</tbody>
</tgroup>
</table>
create a custom ItemReader. A list of the available ItemReaders can be
found in Appendix A.</para>
<para>The Item Reader is a basic interface for generic input operations.
Subclasses implementing this interface will be responsible for reading

View File

@@ -435,8 +435,8 @@
the data from the input source and maps the line to the Trade object.
<para>
<programlisting>
trade = (Trade) tradeFieldSetMapper.mapLine(inputSource.readFieldSet());
</programlisting>
trade = (Trade) tradeFieldSetMapper.mapLine(inputSource.readFieldSet());
</programlisting>
</para> If data exists and an object is returned it is simply passed to
the output source. If there is no data to read an ExitStatus with the
status of FINISHED is returned from the Tasklet.</para>
@@ -507,88 +507,88 @@
<programlisting>
&lt;import resource="BatchArchConfig.xml" /&gt;
&lt;bean id="simpleTaskletJob" parent="Job"&gt;
&lt;property name="name" value="fixedLengthImportJob" /&gt;
&lt;property name="steps"&gt;
&lt;list&gt;
&lt;bean id="tradeStep" parent="Step"&gt;
&lt;property name="name" value="ImportTradeDataStep" /&gt;
&lt;property name="module"&gt;
&lt;bean class="com.accenture.adsj.refapp.batch.module.SimpleTradeTasklet"&gt;
&lt;property name="inputTemplate" ref="fileInputTemplate" /&gt;
&lt;property name="tradeDbWriter" ref="tradeWriter" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="commitFrequency" value="5" /&gt;
&lt;property name="startPolicy"&gt;
&lt;bean class="org.springframework.batch.container.conf.StartPolicy"&gt;
&lt;property name="ignoreComplete" value="true" /&gt;
&lt;property name="restartEnabled" value="true" /&gt;
&lt;property name="startlimit" value="12" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="exceptionPolicy"&gt;
&lt;bean class="org.springframework.batch.container.conf.ExceptionPolicy"&gt;
&lt;property name="totalExceptionLimit" value="20" /&gt;
&lt;property name="transactionInvalidExceptionLimit" value="20" /&gt;
&lt;property name="transactionValidExceptionLimit" value="5" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="tradeWriter" class="com.accenture.adsj.refapp.batch.dao.DbTradeWriter"&gt;
&lt;property name="jdbcTemplate" ref="jdbcTemplate" /&gt;
&lt;property name="incrementer"&gt;
&lt;bean parent="incrementerParent"&gt;
&lt;property name="incrementerName" value="TRADE_SEQ" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="fileInputTemplate" class="org.springframework.batch.container.io.file.support.FlatFileInputTemplate"&gt;
&lt;property name="name" value="FileInputSource" /&gt;
&lt;property name="fileLocatorStrategy" ref="fileLocator" /&gt;
&lt;property name="tokenizer"&gt;
&lt;bean class="org.springframework.batch.container.io.file.support.FixedLineTokenizer"&gt;
&lt;property name="fileDescriptor" ref="fixedFileDescriptor" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="simpleTaskletJob" parent="Job"&gt;
&lt;property name="name" value="fixedLengthImportJob" /&gt;
&lt;property name="steps"&gt;
&lt;list&gt;
&lt;bean id="tradeStep" parent="Step"&gt;
&lt;property name="name" value="ImportTradeDataStep" /&gt;
&lt;property name="module"&gt;
&lt;bean class="com.accenture.adsj.refapp.batch.module.SimpleTradeTasklet"&gt;
&lt;property name="inputTemplate" ref="fileInputTemplate" /&gt;
&lt;property name="tradeDbWriter" ref="tradeWriter" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="commitFrequency" value="5" /&gt;
&lt;property name="startPolicy"&gt;
&lt;bean class="org.springframework.batch.container.conf.StartPolicy"&gt;
&lt;property name="ignoreComplete" value="true" /&gt;
&lt;property name="restartEnabled" value="true" /&gt;
&lt;property name="startlimit" value="12" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="exceptionPolicy"&gt;
&lt;bean class="org.springframework.batch.container.conf.ExceptionPolicy"&gt;
&lt;property name="totalExceptionLimit" value="20" /&gt;
&lt;property name="transactionInvalidExceptionLimit" value="20" /&gt;
&lt;property name="transactionValidExceptionLimit" value="5" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="tradeWriter" class="com.accenture.adsj.refapp.batch.dao.DbTradeWriter"&gt;
&lt;property name="jdbcTemplate" ref="jdbcTemplate" /&gt;
&lt;property name="incrementer"&gt;
&lt;bean parent="incrementerParent"&gt;
&lt;property name="incrementerName" value="TRADE_SEQ" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="fileInputTemplate" class="org.springframework.batch.container.io.file.support.FlatFileInputTemplate"&gt;
&lt;property name="name" value="FileInputSource" /&gt;
&lt;property name="fileLocatorStrategy" ref="fileLocator" /&gt;
&lt;property name="tokenizer"&gt;
&lt;bean class="org.springframework.batch.container.io.file.support.FixedLineTokenizer"&gt;
&lt;property name="fileDescriptor" ref="fixedFileDescriptor" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="fixedFileDescriptor" class="org.springframework.batch.container.io.support.DefaultFileDescriptor"&gt;
&lt;property name="recordDescriptors"&gt;
&lt;bean class="org.springframework.batch.container.io.support.DefaultRecordDescriptor"&gt;
&lt;property name="fieldDescriptors"&gt;
&lt;list&gt;
&lt;bean class="org.springframework.batch.container.io.support.DefaultFieldDescriptor"&gt;
&lt;property name="name" value="ISIN" /&gt;
&lt;property name="length" value="12" /&gt;
&lt;/bean&gt;
&lt;bean class="org.springframework.batch.container.io.support.DefaultFieldDescriptor"&gt;
&lt;property name="name" value="Quantity" /&gt;
&lt;property name="length" value="3" /&gt;
&lt;/bean&gt;
&lt;bean class="org.springframework.batch.container.io.support.DefaultFieldDescriptor"&gt;
&lt;property name="name" value="Price" /&gt;
&lt;property name="length" value="5" /&gt;
&lt;/bean&gt;
&lt;bean class="org.springframework.batch.container.io.support.DefaultFieldDescriptor"&gt;
&lt;property name="name" value="Customer" /&gt;
&lt;property name="length" value="9" /&gt;
&lt;/bean&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="recordDescriptors"&gt;
&lt;bean class="org.springframework.batch.container.io.support.DefaultRecordDescriptor"&gt;
&lt;property name="fieldDescriptors"&gt;
&lt;list&gt;
&lt;bean class="org.springframework.batch.container.io.support.DefaultFieldDescriptor"&gt;
&lt;property name="name" value="ISIN" /&gt;
&lt;property name="length" value="12" /&gt;
&lt;/bean&gt;
&lt;bean class="org.springframework.batch.container.io.support.DefaultFieldDescriptor"&gt;
&lt;property name="name" value="Quantity" /&gt;
&lt;property name="length" value="3" /&gt;
&lt;/bean&gt;
&lt;bean class="org.springframework.batch.container.io.support.DefaultFieldDescriptor"&gt;
&lt;property name="name" value="Price" /&gt;
&lt;property name="length" value="5" /&gt;
&lt;/bean&gt;
&lt;bean class="org.springframework.batch.container.io.support.DefaultFieldDescriptor"&gt;
&lt;property name="name" value="Customer" /&gt;
&lt;property name="length" value="9" /&gt;
&lt;/bean&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="tradeLineMapper" class="com.accenture.adsj.refapp.batch.mapping.TradeRowMapper" /&gt;
&lt;bean class="com.accenture.adsj.refapp.batch.advice.LogAdvice" id="logAdvice" /&gt;
&lt;aop:config&gt;
&lt;aop:aspect id="logging" ref="logAdvice"&gt;
&lt;aop:around pointcut-ref="pointcut" method="doBasicLogging" /&gt;
&lt;aop:pointcut id="pointcut" expression="execution(* org.springframework.batch.container.dao.*.*(..))" /&gt;
&lt;/aop:aspect&gt;
&lt;aop:aspect id="logging" ref="logAdvice"&gt;
&lt;aop:around pointcut-ref="pointcut" method="doBasicLogging" /&gt;
&lt;aop:pointcut id="pointcut" expression="execution(* org.springframework.batch.container.dao.*.*(..))" /&gt;
&lt;/aop:aspect&gt;
&lt;/aop:config&gt;
&lt;/beans&gt;
@@ -806,13 +806,13 @@
src/main/resources/data/footballjob/input/. Each line within this file
represents a player, with a unique id, the players name, position, etc:
<programlisting>
AbduKa00,Abdul-Jabbar,Karim,rb,1974,1996
AbduRa00,Abdullah,Rabih,rb,1975,1999
AberWa00,Abercrombie,Walter,rb,1959,1982
AbraDa00,Abramowicz,Danny,wr,1945,1967
AdamBo00,Adams,Bob,te,1946,1969
AdamCh00,Adams,Charlie,wr,1979,2003
</programlisting></para>
AbduKa00,Abdul-Jabbar,Karim,rb,1974,1996
AbduRa00,Abdullah,Rabih,rb,1975,1999
AberWa00,Abercrombie,Walter,rb,1959,1982
AbraDa00,Abramowicz,Danny,wr,1945,1967
AdamBo00,Adams,Bob,te,1946,1969
AdamCh00,Adams,Charlie,wr,1979,2003
</programlisting></para>
<para>One of the first noticeable characteristics of the file is that each
data element is separated by a comma, a format most are familiar with
@@ -828,13 +828,13 @@
<para>The second file, games.csv is formatted the same as the previous
example, and resides in the same directory: <programlisting>
AbduKa00,1996,mia,10,nwe,0,0,0,0,0,29,104,,16,2
AbduKa00,1996,mia,11,clt,0,0,0,0,0,18,70,,11,2
AbduKa00,1996,mia,12,oti,0,0,0,0,0,18,59,,0,0
AbduKa00,1996,mia,13,pit,0,0,0,0,0,16,57,,0,0
AbduKa00,1996,mia,14,rai,0,0,0,0,0,18,39,,7,0
AbduKa00,1996,mia,15,nyg,0,0,0,0,0,17,96,,14,0
</programlisting></para>
AbduKa00,1996,mia,10,nwe,0,0,0,0,0,29,104,,16,2
AbduKa00,1996,mia,11,clt,0,0,0,0,0,18,70,,11,2
AbduKa00,1996,mia,12,oti,0,0,0,0,0,18,59,,0,0
AbduKa00,1996,mia,13,pit,0,0,0,0,0,16,57,,0,0
AbduKa00,1996,mia,14,rai,0,0,0,0,0,18,39,,7,0
AbduKa00,1996,mia,15,nyg,0,0,0,0,0,17,96,,14,0
</programlisting></para>
<para>Each line in the file represents an individual players performance
in a particular game, containing such statistics as passing yards,
@@ -882,14 +882,14 @@
file which can be found in the jobs folder under src/main/resources. When
you drill down into the footballjob you will see that the configuration
has a list of steps: <programlisting>
&lt;property name="steps"&gt;
&lt;list&gt;
&lt;bean id="playerload"&gt; ... &lt;/bean&gt;
&lt;bean id="gameLoad"&gt; ... &lt;/bean
&lt;bean id="playerSummarization"&gt; ... &lt;/bean&gt;
&lt;/list&gt;
&lt;/property&gt;
</programlisting></para>
&lt;property name="steps"&gt;
&lt;list&gt;
&lt;bean id="playerload"&gt; ... &lt;/bean&gt;
&lt;bean id="gameLoad"&gt; ... &lt;/bean
&lt;bean id="playerSummarization"&gt; ... &lt;/bean&gt;
&lt;/list&gt;
&lt;/property&gt;
</programlisting></para>
<para>The step is run until there is no more input to process, which in
this case would mean that each file has been completely processed. To
@@ -907,16 +907,16 @@
<para>Now that weve discussed the entire flow of the batch job, we can
dive deeper into the first step: playerLoad: <programlisting>
&lt;bean id="playerload" class="org.springframework.batch...SimpleStepConfiguration"&gt;
&lt;property name="commitInterval" value="100" /&gt;
&lt;property name="tasklet"&gt;
&lt;bean class="org.springframework...RestartableItemProviderTasklet"&gt;
&lt;property name="itemProvider"&gt;...&lt;/property&gt;
&lt;property name="itemProcessor"&gt;...&lt;/property&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;
</programlisting></para>
&lt;bean id="playerload" class="org.springframework.batch...SimpleStepConfiguration"&gt;
&lt;property name="commitInterval" value="100" /&gt;
&lt;property name="tasklet"&gt;
&lt;bean class="org.springframework...RestartableItemProviderTasklet"&gt;
&lt;property name="itemProvider"&gt;...&lt;/property&gt;
&lt;property name="itemProcessor"&gt;...&lt;/property&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;
</programlisting></para>
<para>The root bean in this case is a StepConfiguration, which can be
considered a blueprint of sorts that tells the execution environment
@@ -978,17 +978,17 @@
class="org.springframework.batch.io.file.support.DefaultFlatFileInputSource"&gt;
&lt;property name="resource"&gt;
&lt;bean class="org.springframework.core.io.ClassPathResource"&gt;
&lt;constructor-arg value="data/footballjob/input/player.csv" /&gt;
&lt;constructor-arg value="data/footballjob/input/player.csv" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="tokenizer"&gt;
&lt;bean class = "org.springframework.batch.io.file.support.transform.DelimitedLineTokenizer"&gt;
&lt;property name="names"
value="ID,lastName,firstName,position,birthYear,debutYear" /&gt;
value="ID,lastName,firstName,position,birthYear,debutYear" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;
</programlisting></para>
</programlisting></para>
<para>There are two required dependencies of the input source; the first
is a resource to read in, which is the file to process. The second
@@ -1008,24 +1008,24 @@ class="org.springframework.batch.io.file.support.DefaultFlatFileInputSource"&gt;
You can see this below: <programlisting>
public class PlayerMapper implements FieldSetMapper {
public Object mapLine(FieldSet fs) {
if(fs == null){
return null;
}
Player player = new Player();
player.setID(fs.readString("ID"));
player.setLastName(fs.readString("lastName"));
player.setFirstName(fs.readString("firstName"));
player.setPosition(fs.readString("position"));
player.setDebutYear(fs.readInt("debutYear"));
player.setBirthYear(fs.readInt("birthYear"));
return player;
}
public Object mapLine(FieldSet fs) {
if(fs == null){
return null;
}
Player player = new Player();
player.setID(fs.readString("ID"));
player.setLastName(fs.readString("lastName"));
player.setFirstName(fs.readString("firstName"));
player.setPosition(fs.readString("position"));
player.setDebutYear(fs.readInt("debutYear"));
player.setBirthYear(fs.readInt("birthYear"));
return player;
}
}
</programlisting></para>
</programlisting></para>
<para>The flow of the ItemProvider, in this case, starts with a call to
readFieldSet on the InputSource. The next line in the file is read in as a
@@ -1048,23 +1048,23 @@ public class PlayerMapper implements FieldSetMapper {
returns a domain object to the processor. However, in this case, the input
source is the database, not a file: <programlisting>
&lt;bean id="playerSummarizationSource"
class="org.springframework.batch.io.sql.SqlCursorInputSource"&gt;
&lt;property name="dataSource" ref="dataSource" /&gt;
&lt;property name="mapper"&gt;
&lt;bean class="sample.mapping.PlayerSummaryMapper" /&gt;
&lt;/property&gt;
&lt;property name="sql"&gt;
&lt;value&gt;
SELECT games.player_id, games.year, SUM(COMPLETES),
SUM(ATTEMPTS), SUM(PASSING_YARDS), SUM(PASSING_TD),
SUM(INTERCEPTIONS), SUM(RUSHES), SUM(RUSH_YARDS),
SUM(RECEPTIONS), SUM(RECEPTIONS_YARDS), SUM(TOTAL_TD)
from games, players where players.player_id =
games.player_id group by games.player_id, games.year
&lt;/value&gt;
&lt;/property&gt;
class="org.springframework.batch.io.sql.SqlCursorInputSource"&gt;
&lt;property name="dataSource" ref="dataSource" /&gt;
&lt;property name="mapper"&gt;
&lt;bean class="sample.mapping.PlayerSummaryMapper" /&gt;
&lt;/property&gt;
&lt;property name="sql"&gt;
&lt;value&gt;
SELECT games.player_id, games.year, SUM(COMPLETES),
SUM(ATTEMPTS), SUM(PASSING_YARDS), SUM(PASSING_TD),
SUM(INTERCEPTIONS), SUM(RUSHES), SUM(RUSH_YARDS),
SUM(RECEPTIONS), SUM(RECEPTIONS_YARDS), SUM(TOTAL_TD)
from games, players where players.player_id =
games.player_id group by games.player_id, games.year
&lt;/value&gt;
&lt;/property&gt;
&lt;/bean&gt;
</programlisting></para>
</programlisting></para>
<para>The SqlCursorInputSource has three dependences: <itemizedlist>
<listitem>
@@ -1091,4 +1091,4 @@ public class PlayerMapper implements FieldSetMapper {
to wrap the ItemProcessors and output each record as it is processed to
the logger, which will greatly impact performance.</para>
</section>
</chapter>
</chapter>