BATCH-1035: Added section on Late binding.
This commit is contained in:
@@ -90,7 +90,7 @@
|
||||
<para>In Spring Batch, a Job is simply a continer for Steps. It combines
|
||||
multiple steps that belong logically together in a flow and allows for
|
||||
configuration of properties global to all steps, such as restartability.
|
||||
The job configuration contains: </para>
|
||||
The job configuration contains:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
@@ -303,7 +303,7 @@
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>JOB_INSTANCE_ID</entry>
|
||||
<entry>JOB_INST_ID</entry>
|
||||
|
||||
<entry>JOB_NAME</entry>
|
||||
</row>
|
||||
@@ -323,7 +323,7 @@
|
||||
<tgroup cols="4">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>JOB_INSTANCE_ID</entry>
|
||||
<entry>JOB_INST_ID</entry>
|
||||
|
||||
<entry>TYPE_CD</entry>
|
||||
|
||||
@@ -339,7 +339,7 @@
|
||||
|
||||
<entry>schedule.Date</entry>
|
||||
|
||||
<entry>2008-01-01 00:00:00</entry>
|
||||
<entry>2008-01-01</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -351,9 +351,9 @@
|
||||
<tgroup cols="5">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>JOB_EXECUTION_ID</entry>
|
||||
<entry>JOB_EXEC_ID</entry>
|
||||
|
||||
<entry>JOB_INSTANCE_ID</entry>
|
||||
<entry>JOB_INST_ID</entry>
|
||||
|
||||
<entry>START_TIME</entry>
|
||||
|
||||
@@ -367,9 +367,9 @@
|
||||
|
||||
<entry>1</entry>
|
||||
|
||||
<entry>2008-01-01 21:00:23.571</entry>
|
||||
<entry>2008-01-01 21:00</entry>
|
||||
|
||||
<entry>2008-01-01 21:30:17.132</entry>
|
||||
<entry>2008-01-01 21:30</entry>
|
||||
|
||||
<entry>FAILED</entry>
|
||||
</row>
|
||||
@@ -378,8 +378,8 @@
|
||||
</table>
|
||||
|
||||
<note>
|
||||
<para>extra columns in the tables have been removed for added
|
||||
clarity.</para>
|
||||
<para>column names may have been abbreviated or removed for clarity
|
||||
and formatting</para>
|
||||
</note>
|
||||
|
||||
<para>Now that the job has failed, let's assume that it took the entire
|
||||
@@ -409,7 +409,7 @@
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>JOB_INSTANCE_ID</entry>
|
||||
<entry>JOB_INST_ID</entry>
|
||||
|
||||
<entry>JOB_NAME</entry>
|
||||
</row>
|
||||
@@ -435,7 +435,7 @@
|
||||
<tgroup cols="4">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>JOB_INSTANCE_ID</entry>
|
||||
<entry>JOB_INST_ID</entry>
|
||||
|
||||
<entry>TYPE_CD</entry>
|
||||
|
||||
@@ -473,9 +473,9 @@
|
||||
<tgroup cols="5">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>JOB_EXECUTION_ID</entry>
|
||||
<entry>JOB_EXEC_ID</entry>
|
||||
|
||||
<entry>JOB_INSTANCE_ID</entry>
|
||||
<entry>JOB_INST_ID</entry>
|
||||
|
||||
<entry>START_TIME</entry>
|
||||
|
||||
@@ -522,6 +522,11 @@
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<note>
|
||||
<para>column names may have been abbreviated or removed for clarity
|
||||
and formatting</para>
|
||||
</note>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -717,7 +722,7 @@
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>JOB_INSTANCE_ID</entry>
|
||||
<entry>JOB_INST_ID</entry>
|
||||
|
||||
<entry>JOB_NAME</entry>
|
||||
</row>
|
||||
@@ -735,7 +740,7 @@
|
||||
<tgroup cols="4">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>JOB_INSTANCE_ID</entry>
|
||||
<entry>JOB_INST_ID</entry>
|
||||
|
||||
<entry>TYPE_CD</entry>
|
||||
|
||||
@@ -751,7 +756,7 @@
|
||||
|
||||
<entry>schedule.Date</entry>
|
||||
|
||||
<entry>2008-01-01 00:00:00</entry>
|
||||
<entry>2008-01-01 </entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -761,9 +766,9 @@
|
||||
<tgroup cols="5">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>JOB_EXECUTION_ID</entry>
|
||||
<entry>JOB_EXEC_ID</entry>
|
||||
|
||||
<entry>JOB_INSTANCE_ID</entry>
|
||||
<entry>JOB_INST_ID</entry>
|
||||
|
||||
<entry>START_TIME</entry>
|
||||
|
||||
@@ -777,9 +782,9 @@
|
||||
|
||||
<entry>1</entry>
|
||||
|
||||
<entry>2008-01-01 21:00:23.571</entry>
|
||||
<entry>2008-01-01 21:00</entry>
|
||||
|
||||
<entry>2008-01-01 21:30:17.132</entry>
|
||||
<entry>2008-01-01 21:30</entry>
|
||||
|
||||
<entry>FAILED</entry>
|
||||
</row>
|
||||
@@ -791,9 +796,9 @@
|
||||
<tgroup cols="6">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>STEP_EXECUTION_ID</entry>
|
||||
<entry>STEP_EXEC_ID</entry>
|
||||
|
||||
<entry>JOB_EXECUTION_ID</entry>
|
||||
<entry>JOB_EXEC_ID</entry>
|
||||
|
||||
<entry>STEP_NAME</entry>
|
||||
|
||||
@@ -811,9 +816,9 @@
|
||||
|
||||
<entry>loadDate</entry>
|
||||
|
||||
<entry>2008-01-01 21:00:23.571</entry>
|
||||
<entry>2008-01-01 21:00</entry>
|
||||
|
||||
<entry>2008-01-01 21:30:17.132</entry>
|
||||
<entry>2008-01-01 21:30</entry>
|
||||
|
||||
<entry>FAILED</entry>
|
||||
</row>
|
||||
@@ -825,7 +830,7 @@
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>STEP_EXECUTION_ID</entry>
|
||||
<entry>STEP_EXEC_ID</entry>
|
||||
|
||||
<entry>SHORT_CONTEXT</entry>
|
||||
</row>
|
||||
@@ -945,8 +950,8 @@
|
||||
|
||||
<programlisting> public interface JobLauncher {
|
||||
|
||||
public JobExecution run(Job job, JobParameters jobParameters) throws JobExecutionAlreadyRunningException,
|
||||
JobRestartException;
|
||||
public JobExecution run(Job job, JobParameters jobParameters)
|
||||
throws JobExecutionAlreadyRunningException, JobRestartException;
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 44 KiB |
@@ -154,11 +154,12 @@
|
||||
|
||||
<programlisting>
|
||||
void afterJob(JobExecution jobExecution){
|
||||
if( jobExecution.getStatus = BatchStatus.COMPLETED ){
|
||||
//job success
|
||||
}
|
||||
else if(jobExecution.getStatus = BatchStatus.FAILED){
|
||||
//job failure
|
||||
if( jobExecution.getStatus = BatchStatus.COMPLETED ){
|
||||
//job success
|
||||
}
|
||||
else if(jobExecution.getStatus = BatchStatus.FAILED){
|
||||
//job failure
|
||||
}
|
||||
}
|
||||
|
||||
</programlisting>
|
||||
@@ -379,7 +380,8 @@
|
||||
that you just don't need to persist status for a particular job. Spring
|
||||
batch provides a solution:</para>
|
||||
|
||||
<programlisting> <bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean" /></programlisting>
|
||||
<programlisting> <bean id="jobRepository"
|
||||
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean" /></programlisting>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -182,11 +182,14 @@
|
||||
fields so that the fields may be accessed either by index or name as
|
||||
patterned after <classname>ResultSet</classname>:</para>
|
||||
|
||||
<programlisting> String[] tokens = new String[]{"foo", "1", "true"};
|
||||
<programlisting>
|
||||
String[] tokens = new String[]{"foo", "1", "true"};
|
||||
FieldSet fs = new DefaultFieldSet(tokens);
|
||||
String name = fs.readString(0);
|
||||
int value = fs.readInt(1);
|
||||
boolean booleanValue = fs.readBoolean(2);</programlisting>
|
||||
boolean booleanValue = fs.readBoolean(2);
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>There are many more options on the <classname>FieldSet</classname>
|
||||
interface, such as <classname>Date</classname>, long,
|
||||
@@ -217,7 +220,7 @@
|
||||
guide will not go into the details of creating
|
||||
<classname>Resource</classname> objects. However, a simple example of a
|
||||
file system resource can be found below: <programlisting>
|
||||
Resource resource = new FileSystemResource("resources/trades.csv");
|
||||
Resource resource = new FileSystemResource("resources/trades.csv");
|
||||
</programlisting></para>
|
||||
|
||||
<para>In complex batch environments the directory structures are often
|
||||
@@ -320,10 +323,13 @@
|
||||
<para>As with <classname>RowMapper</classname>, which takes a low
|
||||
level construct such as <classname>ResultSet and returns an Object,
|
||||
flat file procesing requires the same construct to convert a String
|
||||
line into an Object:</classname><programlisting>public interface LineMapper<T> {
|
||||
line into an Object:</classname><programlisting>
|
||||
public interface LineMapper<T> {
|
||||
|
||||
T mapLine(String line, int lineNumber) throws Exception;
|
||||
}</programlisting></para>
|
||||
T mapLine(String line, int lineNumber) throws Exception;
|
||||
}
|
||||
|
||||
</programlisting></para>
|
||||
|
||||
<para>The basic constract is that, given the current line, and the
|
||||
line number its associated with, return a resulting domain object.
|
||||
@@ -349,11 +355,14 @@
|
||||
necessary. In Spring Batch, this is called a
|
||||
<classname>LineTokenizer</classname>:</para>
|
||||
|
||||
<programlisting> public interface LineTokenizer {
|
||||
<programlisting>
|
||||
public interface LineTokenizer {
|
||||
|
||||
FieldSet tokenize(String line);
|
||||
|
||||
}</programlisting>
|
||||
}
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>The contract of a <classname>LineTokenizer</classname> is such
|
||||
that, given a line of input (in theory the
|
||||
@@ -397,11 +406,14 @@
|
||||
<classname>LineTokenizer</classname> to translate a line of data from
|
||||
a resource into an object of the desired type:</para>
|
||||
|
||||
<programlisting> public interface FieldSetMapper<T> {
|
||||
<programlisting>
|
||||
public interface FieldSetMapper<T> {
|
||||
|
||||
T mapFieldSet(FieldSet fieldSet);
|
||||
|
||||
}</programlisting>
|
||||
}
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>The pattern used is the same as <classname>RowMapper</classname>
|
||||
used by <classname>JdbcTemplate</classname>.</para>
|
||||
@@ -459,7 +471,9 @@
|
||||
public void setFieldSetMapper(FieldSetMapper<T> fieldSetMapper) {
|
||||
this.fieldSetMapper = fieldSetMapper;
|
||||
}
|
||||
}</programlisting>
|
||||
}
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>The above functionality is provided in a default implementation,
|
||||
rather than being built into the reader itself (as was done in
|
||||
@@ -522,7 +536,8 @@
|
||||
|
||||
return player;
|
||||
}
|
||||
} </programlisting></para>
|
||||
}
|
||||
</programlisting></para>
|
||||
|
||||
<para>The file can then be read by correctly constructing a
|
||||
<classname>FlatFileItemReader</classname> and calling
|
||||
@@ -583,7 +598,8 @@
|
||||
return player;
|
||||
}
|
||||
|
||||
} </programlisting></para>
|
||||
}
|
||||
</programlisting></para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
@@ -599,14 +615,17 @@
|
||||
<classname>FieldSetMapper</classname> configuration looks like the
|
||||
following:</para>
|
||||
|
||||
<programlisting> <bean id="fieldSetMapper"
|
||||
<programlisting>
|
||||
<bean id="fieldSetMapper"
|
||||
class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
|
||||
<property name="prototypeBeanName" value="player" />
|
||||
</bean>
|
||||
|
||||
<bean id="player"
|
||||
class="org.springframework.batch.sample.domain.Player"
|
||||
scope="prototype" /></programlisting>
|
||||
scope="prototype" />
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>For each entry in the <classname>FieldSet</classname>, the
|
||||
mapper will look for a corresponding setter on a new instance of the
|
||||
@@ -680,7 +699,8 @@
|
||||
<classname>ApplicationContext</classname>:</para>
|
||||
|
||||
<programlisting>
|
||||
<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
|
||||
<bean id="customEditorConfigurer"
|
||||
class="org.springframework.beans.factory.config.CustomEditorConfigurer">
|
||||
<property name="customEditors">
|
||||
<map>
|
||||
<entry key="org.springframework.batch.item.file.transform.Range[]">
|
||||
@@ -717,7 +737,8 @@
|
||||
PrefixMatchingCompositeLineTokenizer makes this easier by matching the
|
||||
prefix in a line with a particular tokenizer:</para>
|
||||
|
||||
<programlisting> <bean id="orderFileDescriptor"
|
||||
<programlisting>
|
||||
<bean id="orderFileDescriptor"
|
||||
class="org.springframework.batch.io.file.transform.PrefixMatchingCompositeLineTokenizer">
|
||||
<property name="tokenizers">
|
||||
<map>
|
||||
@@ -733,7 +754,9 @@
|
||||
<entry key="" value-ref="defaultLineDescriptor" />
|
||||
</map>
|
||||
</property>
|
||||
</bean></programlisting>
|
||||
</bean>
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>This ensures that the line will be parsed correctly, which is
|
||||
especially important for fixed length input. Any users of the
|
||||
@@ -863,11 +886,14 @@
|
||||
writing to a file. In Spring Batch this is the
|
||||
<classname>LineAggregator</classname>:</para>
|
||||
|
||||
<programlisting> public interface LineAggregator<T> {
|
||||
<programlisting>
|
||||
public interface LineAggregator<T> {
|
||||
|
||||
public String aggregate(T item);
|
||||
|
||||
}</programlisting>
|
||||
}
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>The <classname>LineAggregator</classname> is the opposite of a
|
||||
<classname>LineTokenizer</classname>.
|
||||
@@ -927,20 +953,26 @@
|
||||
<classname>FlatFileItemWriter</classname> expresses this in
|
||||
code:</para>
|
||||
|
||||
<programlisting> public void write(T item) throws Exception {
|
||||
<programlisting>
|
||||
public void write(T item) throws Exception {
|
||||
write(lineAggregator.aggregate(item) + LINE_SEPARATOR);
|
||||
}</programlisting>
|
||||
}
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>A simple configuration would look like the following:</para>
|
||||
|
||||
<programlisting> <bean id="itemWriter"
|
||||
<programlisting>
|
||||
<bean id="itemWriter"
|
||||
class="org.springframework.batch.io.file.FlatFileItemWriter">
|
||||
<property name="resource"
|
||||
value="file:target/test-outputs/20070122.testStream.multilineStep.txt" />
|
||||
<property name="lineAggregator">
|
||||
<bean class="org.springframework.batch.item.file.transform.PassThroughLineAggregator"/>
|
||||
</property>
|
||||
</bean></programlisting>
|
||||
</bean>
|
||||
|
||||
</programlisting>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
@@ -1201,12 +1233,12 @@
|
||||
<imageobject role="fo">
|
||||
<imagedata align="center"
|
||||
fileref="src/site/docbook/reference/images/xmlinput.png"
|
||||
format="PNG" width="50%" />
|
||||
format="PNG" width="40%" />
|
||||
</imageobject>
|
||||
|
||||
<imageobject role="html">
|
||||
<imagedata align="center" fileref="images/xmlinput.png" format="PNG"
|
||||
width="50%" />
|
||||
width="40%" />
|
||||
</imageobject>
|
||||
|
||||
<caption><para>Figure 3.1: XML Input</para></caption>
|
||||
@@ -1228,12 +1260,12 @@
|
||||
<imageobject role="fo">
|
||||
<imagedata align="center"
|
||||
fileref="src/site/docbook/reference/images/oxm-fragments.png"
|
||||
format="PNG" width="50%" />
|
||||
format="PNG" width="40%" />
|
||||
</imageobject>
|
||||
|
||||
<imageobject role="html">
|
||||
<imagedata align="center" fileref="images/oxm-fragments.png"
|
||||
format="PNG" width="50%" />
|
||||
format="PNG" width="40%" />
|
||||
</imageobject>
|
||||
|
||||
<caption><para>Figure 3.2: OXM Binding</para></caption>
|
||||
@@ -2241,7 +2273,8 @@
|
||||
<programlisting>
|
||||
<job id="ioSampleJob">
|
||||
<step name="step1">
|
||||
<tasklet reader="fooReader" processor="fooProcessor" writer="compositeItemWriter" commit-interval="2"/>
|
||||
<tasklet reader="fooReader" processor="fooProcessor" writer="compositeItemWriter"
|
||||
commit-interval="2"/>
|
||||
<streams>
|
||||
<stream ref="barWriter" />
|
||||
</streams>
|
||||
@@ -2357,11 +2390,14 @@
|
||||
rather provides a very simple interface that can be implemented by any
|
||||
number of frameworks:</para>
|
||||
|
||||
<programlisting> public interface Validator {
|
||||
<programlisting>
|
||||
public interface Validator {
|
||||
|
||||
void validate(Object value) throws ValidationException;
|
||||
|
||||
}</programlisting>
|
||||
}
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>The contract is that the <methodname>validate</methodname> method
|
||||
will throw an exception if the object is invalid, and return normally if
|
||||
@@ -2381,9 +2417,14 @@
|
||||
<value>
|
||||
<![CDATA[
|
||||
{ orderId : ? > 0 AND ? <= 9999999999 : 'Incorrect order ID' : 'error.order.id' }
|
||||
{ totalLines : ? = size(lineItems) : 'Bad count of order lines' : 'error.order.lines.badcount'}
|
||||
{ customer.registered : customer.businessCustomer = FALSE OR ? = TRUE : 'Business customer must be registered' : 'error.customer.registration'}
|
||||
{ customer.companyName : customer.businessCustomer = FALSE OR ? HAS TEXT : 'Company name for business customer is mandatory' :'error.customer.companyname'}
|
||||
{ totalLines : ? = size(lineItems) : 'Bad count of order lines'
|
||||
: 'error.order.lines.badcount'}
|
||||
{ customer.registered : customer.businessCustomer = FALSE OR ? = TRUE
|
||||
: 'Business customer must be registered'
|
||||
: 'error.customer.registration'}
|
||||
{ customer.companyName : customer.businessCustomer = FALSE OR ? HAS TEXT
|
||||
: 'Company name for business customer is mandatory'
|
||||
:'error.customer.companyname'}
|
||||
]]>
|
||||
</value>
|
||||
</property>
|
||||
@@ -2468,7 +2509,8 @@
|
||||
basic contract of <classname>ItemReader</classname>,
|
||||
<methodname>read</methodname>:</para>
|
||||
|
||||
<programlisting> public class CustomItemReader<T> implements ItemReader<T>{
|
||||
<programlisting>
|
||||
public class CustomItemReader<T> implements ItemReader<T>{
|
||||
|
||||
List<T> items;
|
||||
|
||||
@@ -2484,7 +2526,9 @@
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}</programlisting>
|
||||
}
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>This very simple class takes a list of items, and returns one at a
|
||||
time, removing it from the list. When the list empty, it returns null,
|
||||
|
||||
@@ -27,12 +27,14 @@
|
||||
|
||||
<mediaobject>
|
||||
<imageobject role="html">
|
||||
<imagedata align="center" fileref="images/meta-data-erd.png" />
|
||||
<imagedata align="center" fileref="images/meta-data-erd.png"
|
||||
width="45%" />
|
||||
</imageobject>
|
||||
|
||||
<imageobject role="html">
|
||||
<imagedata fileref="src/site/docbook/reference/images/meta-data-erd.png"
|
||||
format="PNG" />
|
||||
<imagedata align="center"
|
||||
fileref="src/site/docbook/reference/images/meta-data-erd.png"
|
||||
width="45%" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
@@ -518,13 +520,13 @@ INSERT INTO BATCH_JOB_SEQ values(0);</programlisting>
|
||||
<listitem>
|
||||
<para>The framework will use the meta-data tables to determine if a
|
||||
particular JobInstance has been run before. If it has been run, and
|
||||
the job is not restartable, then an exception will be thrown. </para>
|
||||
the job is not restartable, then an exception will be thrown.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>If an entry for a JobInstance is removed without having
|
||||
completed successfully, the framework will think that the job is new,
|
||||
rather than a restart. </para>
|
||||
rather than a restart.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
@@ -536,4 +538,4 @@ INSERT INTO BATCH_JOB_SEQ values(0);</programlisting>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
</appendix>
|
||||
</appendix>
|
||||
@@ -204,8 +204,8 @@
|
||||
|
||||
<programlisting>
|
||||
<step name="step1">
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="10" <emphasis
|
||||
role="bold">allow-start-if-complete="true"</emphasis>/>
|
||||
<tasklet reader="itemReader" writer="itemWriter" commit-interval="10"
|
||||
<emphasis role="bold">allow-start-if-complete="true"</emphasis>/>
|
||||
</step>
|
||||
|
||||
</programlisting>
|
||||
@@ -484,7 +484,8 @@
|
||||
</tasklet>
|
||||
</step>
|
||||
|
||||
<beans:bean id="compositeWriter" class="org.springframework.batch.item.support.CompositeItemWriter">
|
||||
<beans:bean id="compositeWriter"
|
||||
class="org.springframework.batch.item.support.CompositeItemWriter">
|
||||
<beans:property name="delegates">
|
||||
<beans:list>
|
||||
<beans:ref bean="fileItemWriter1" />
|
||||
@@ -972,13 +973,13 @@
|
||||
<mediaobject>
|
||||
<imageobject role="html">
|
||||
<imagedata align="center" fileref="images/sequential-flow.png"
|
||||
scale="50" width="" />
|
||||
scale="" width="40%" />
|
||||
</imageobject>
|
||||
|
||||
<imageobject role="fo">
|
||||
<imagedata align="center"
|
||||
fileref="src/site/docbook/reference/images/sequential-flow.png"
|
||||
width="75%" />
|
||||
width="40%" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
@@ -1019,13 +1020,13 @@
|
||||
rather than causing failure? <mediaobject>
|
||||
<imageobject role="html">
|
||||
<imagedata align="center" fileref="images/conditional-flow.png"
|
||||
scale="75" width="" />
|
||||
scale="" width="40%" />
|
||||
</imageobject>
|
||||
|
||||
<imageobject role="fo">
|
||||
<imagedata align="center"
|
||||
fileref="src/site/docbook/reference/images/conditional-flow.png"
|
||||
width="75%" />
|
||||
width="40%" />
|
||||
</imageobject>
|
||||
</mediaobject></para>
|
||||
|
||||
@@ -1237,7 +1238,7 @@
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Creating File Names at Runtime</title>
|
||||
<title>Late binding of Job and Step Attributes</title>
|
||||
|
||||
<para>Both the XML and Flat File examples above use the Spring
|
||||
<classname>Resource</classname> abstraction to obtain the file to read
|
||||
@@ -1246,11 +1247,14 @@
|
||||
<classname>java.io.File</classname>. Both XML and Flat File resources
|
||||
can be configured using standard Spring constructs:</para>
|
||||
|
||||
<programlisting> <bean id="flatFileItemReader"
|
||||
<programlisting>
|
||||
<bean id="flatFileItemReader"
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource"
|
||||
value="file://outputs/20070122.testStream.CustomerReportStep.TEMP.txt" />
|
||||
</bean></programlisting>
|
||||
</bean>
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>The above <classname>Resource</classname> will load the file from
|
||||
the file system, at the location specificied. Note that absolute
|
||||
@@ -1260,10 +1264,13 @@
|
||||
may need to be determined at runtime as a parameter to the job. This
|
||||
could be solved using '-D' parameters, i.e. a system property:</para>
|
||||
|
||||
<programlisting><bean id="flatFileItemReader"
|
||||
<programlisting>
|
||||
<bean id="flatFileItemReader"
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource" value="${input.file.name}" />
|
||||
</bean></programlisting>
|
||||
</bean>
|
||||
|
||||
</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
|
||||
@@ -1275,35 +1282,63 @@
|
||||
<para>Often in a batch setting it is preferable to parameterize the file
|
||||
name in the <classname>JobParameters</classname> of the job, instead of
|
||||
through system properties, and access them that way. To allow for this,
|
||||
Spring Batch provides the
|
||||
<classname>StepExecutionResourceProxy</classname>. The proxy can use
|
||||
either job name, step name, or any values from the
|
||||
<classname>JobParameters</classname>, by surrounding them with %:</para>
|
||||
Spring Batch allows for the late binding of various Job and Step
|
||||
attributes:</para>
|
||||
|
||||
<programlisting> <bean id="inputFile"
|
||||
class="org.springframework.batch.core.resource.StepExecutionResourceProxy" />
|
||||
<property name="filePattern" value="//%JOB_NAME%/%STEP_NAME%/%file.name%" />
|
||||
</bean></programlisting>
|
||||
<programlisting>
|
||||
<bean id="flatFileItemReader" scope="step"
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource" value="#{jobParameters[input.file.name]}" />
|
||||
</bean>
|
||||
|
||||
<para>Assuming a job name of 'fooJob', and a step name of 'fooStep', and
|
||||
the key-value pair of 'file.name="fileName.txt"' is in the
|
||||
<classname>JobParameters</classname> the job is started with, the
|
||||
following filename will be passed as the
|
||||
<classname>Resource</classname>:
|
||||
"<filename>//fooJob/fooStep/fileName.txt</filename>". It should be noted
|
||||
that in order for the proxy to have access to the
|
||||
<classname>StepExecution</classname>, it must be registered as a
|
||||
<classname>StepListener</classname>:</para>
|
||||
</programlisting>
|
||||
|
||||
<programlisting> <bean id="fooStep" parent="abstractStep"
|
||||
p:itemReader-ref="itemReader"
|
||||
p:itemWriter-ref="itemWriter">
|
||||
<property name="listeners" ref="inputFile" />
|
||||
</bean></programlisting>
|
||||
<para>Both the <classname>JobExecution</classname> and
|
||||
<classname>StepExecution</classname> level
|
||||
<classname>ExecutionContext</classname> can be access in the same
|
||||
way:</para>
|
||||
|
||||
<para>The <classname>StepListener</classname> interface will be
|
||||
discussed in more detail in Chapter 4. For now, it is sufficient to know
|
||||
that the proxy must be registered.</para>
|
||||
<programlisting>
|
||||
<bean id="flatFileItemReader" scope="step"
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource" value="#{<emphasis role="bold">jobExecutionContext</emphasis>[input.file.name]}" />
|
||||
</bean>
|
||||
|
||||
</programlisting>
|
||||
|
||||
<programlisting>
|
||||
<bean id="flatFileItemReader" scope="step"
|
||||
class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="resource" value="#{<emphasis role="bold">stepExecutionContext</emphasis>[input.file.name]}" />
|
||||
</bean>
|
||||
|
||||
</programlisting>
|
||||
|
||||
<section>
|
||||
<title>Step Scope</title>
|
||||
|
||||
<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>
|
||||
|
||||
<para>Using a scope of <classname>Step</classname> is required in
|
||||
order to use late binding, since the bean cannot actually be
|
||||
instantiated until the <classname>Step</classname> starts, which
|
||||
allows the attributes to be found. Because it is not part of the
|
||||
Spring container by default, it must be added explicitely: </para>
|
||||
|
||||
<programlisting>
|
||||
<bean class="org.springframework.batch.core.scope.StepScope" />
|
||||
|
||||
</programlisting>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
||||
Reference in New Issue
Block a user