diff --git a/docs/src/site/docbook/reference/readersAndWriters.xml b/docs/src/site/docbook/reference/readersAndWriters.xml
index 77ed703bf..172d13aa3 100644
--- a/docs/src/site/docbook/reference/readersAndWriters.xml
+++ b/docs/src/site/docbook/reference/readersAndWriters.xml
@@ -151,61 +151,6 @@
persisted in the database before commit.
-
- List Item Readers and Common Custom Item
- Reader Behavior
-
- The ListItemReader, as mentioned
- above, is useful for testing and probably not too useful as something used
- in typical batch processing. One instructive use is to see how narrow the
- responsiblity of ItemReaders are. They simply provide a method that allows
- us to continue reading items until the items are exhausted much like an
- iterator. In addition,, it is expected that projects will create custom
- Item Readers. As a means of illustrating the standard properties and
- behaviors of other framework-provided ItemReaders like mapping
- unstructured items into objects through the use of tokenizing we will
- extend the ListItemReader to supporting mapping. The ItemReader interface
- defines a single method called read().
- The read() method returns the next object
- to be provided, much like an iterator. The definition of this method will
- contain the logic that decides what object to return, performs any object
- construction or other work that needs to occur, and finally returns the
- object. We inherit this behavior from ListItemReader. We will add two
- methods, setFieldSetMapper(), to enable
- the mapping behavior and setTokenizer(),
- to enabling parsing of List Items. It this example the items in the list
- are a simple array of delimited strings..
-
- Here is our custom list item Reader that supplies mapping or binding
- behavior as follows:
- protected static class ListPlayerReader extends ListItemReader {
- private FieldSetMapper fieldSetMapper;
- private LineTokenizer tokenizer = null;
-
- public ListPlayerReader(List list) {
- super(list);
- }
-
- public void setFieldSetMapper(FieldSetMapper fieldSetMapper) {
- this.fieldSetMapper = fieldSetMapper;
- }
-
- public void setTokenizer(LineTokenizer tokenizer) {
- this.tokenizer = tokenizer;
- }
-
-
- }
-
-
- We will tag it as an Player Reader for reasons you'll see next as we
- map Player objects from input strings. In this example we have inherited
- the read() behavior that allows us to read from a List in memory and
- provided a way to map arbitrary streams into objects and added the ability
- to map FieldSets to objects. We will see how to take advantage of this
- next.
-
-
Flat Files
@@ -517,8 +462,8 @@ boolean booleanValue = fs.readBoolean(2);
FlatFileItemReader itemReader = new FlatFileItemReader();
itemReader.setResource = new FileSystemResource("resources/players.csv");
//DelimitedLineTokenizer defaults to comma as it's delimiter
-itemReader.setLineTokenizer = new DelimitedLineTokenizer();
-itemReader.setFieldSetMapper = new PlayerFieldSetMapper();
+itemReader.setLineTokenizer(new DelimitedLineTokenizer());
+itemReader.setFieldSetMapper(new PlayerFieldSetMapper());
itemReader.read();
@@ -567,7 +512,7 @@ itemReader.read();
- BeanWrapperFieldSetMapper
+ Automapping FieldSets to Domain Objects
For many, having to write a specific FieldSetMapper is equally
as cumbersome as writing a specific RowMapper for a JdbcTemplate.
@@ -595,7 +540,7 @@ itemReader.read();
- FixedLengthLineTokenizer
+ Fixed Length file formats
So far only delimited files have been discussed in much detail,
however, they respresent only half of the file reading picture. Many
@@ -648,7 +593,7 @@ UK21341EAH4521535.11customer5
- PrefixMatchingCompositeLineTokenizer
+ Multiple record types within a single file
All of the file reading examples up to this point have all made
a key assumption for simplicity's sake: one record equals one line.
@@ -820,38 +765,13 @@ FOT;2;2;267.34
Constraints on streaming XML
- StAX API is used for I/O as other standard XML APIs do not fit
- batch processing requirements (DOM loads the whole input into memory at
- once and SAX controls the parsing process allowing the user only to
- provide callbacks).
+ The StAX API is used for I/O as other standard XML parsing APIs do
+ not fit batch processing requirements (DOM loads the whole input into
+ memory at once and SAX controls the parsing process allowing the user
+ only to provide callbacks).
- Spring Batch is not tied to any particular OXM technology. Typical
- use is to delegate OXM
- to Spring WS, which provides uniform abstraction for
- the most popular OXM technologies. However dependency on Spring WS is
- optional and you can choose to implement Spring Batch specific interfaces
- if desired. The relationship to the technologies that OXM supports can be
- shown as the following:
-
-
-
-
-
-
-
-
-
-
- Figure X: OXM Binding
-
-
- Lets take a closer look how XML input and output work in batch. It
+ Lets take a closer look how XML input and output works in batch. It
is assumed the XML resource is a collection of 'fragments' corresponding
to individual records. Note that OXM tools are designed to work with
standalone XML documents rather than XML fragments cut out of an XML
@@ -874,11 +794,37 @@ FOT;2;2;267.34
Figure X: XML Inputs
-
- The StaxEventItemReader configuration provides a typical setup for the processing of records from an XML input stream. First, lets examine a set of xml records that the StaxEventItemReader can process.
-
-
-
+ Spring Batch uses Object/XML Mapping (OXM) to bind fragments to
+ objects. However, Spring Batch is not tied to any particular OXM
+ technology. Typical use is to delegate OXM
+ to Spring WS, which provides uniform abstraction for
+ the most popular OXM technologies. The dependency on Spring WS is optional
+ and you can choose to implement Spring Batch specific interfaces if
+ desired. The relationship to the technologies that OXM supports can be
+ shown as the following:
+
+
+
+
+
+
+
+
+
+
+ Figure X: OXM Binding
+
+
+ The StaxEventItemReader configuration provides a typical setup for
+ the processing of records from an XML input stream. First, lets examine a
+ set of xml records that the StaxEventItemReader can process.
+
+
<?xml version="1.0" encoding="UTF-8"?>
<records>
<trade xmlns="http://springframework.org/batch/sample/io/oxm/domain">
@@ -899,63 +845,31 @@ FOT;2;2;267.34
<price>99.99</price>
<customer>Customer3</customer>
</trade>
- <trade xmlns="http://springframework.org/batch/sample/io/oxm/domain">
- <isin>XYZ0001</isin>
- <quantity>5</quantity>
- <price>11.39</price>
- <customer>Customer1</customer>
- </trade>
- <trade xmlns="http://springframework.org/batch/sample/io/oxm/domain">
- <isin>XYZ0002</isin>
- <quantity>2</quantity>
- <price>72.99</price>
- <customer>Customer2c</customer>
- </trade>
- <trade xmlns="http://springframework.org/batch/sample/io/oxm/domain">
- <isin>XYZ0003</isin>
- <quantity>9</quantity>
- <price>99.99</price>
- <customer>Customer3</customer>
- </trade>
- <trade xmlns="http://springframework.org/batch/sample/io/oxm/domain">
- <isin>XYZ0001</isin>
- <quantity>5</quantity>
- <price>11.39</price>
- <customer>Customer1</customer>
- </trade>
- <trade xmlns="http://springframework.org/batch/sample/io/oxm/domain">
- <isin>XYZ0002</isin>
- <quantity>2</quantity>
- <price>72.99</price>
- <customer>Customer2c</customer>
- </trade>
- <trade xmlns="http://springframework.org/batch/sample/io/oxm/domain">
- <isin>XYZ0003</isin>
- <quantity>9</quantity>
- <price>99.99</price>
- <customer>Customer3</customer>
- </trade>
</records>
-
-
+
-
- To be able to process the XML records we need the following:
+ To be able to process the XML records we need the following:
-
- Root Element Name - this is name of the root element of the fragment that constitutes the object to be mapped in. The example configuration
- demonstrates this with the value of trade.
-
-
- Resource - This is a Spring Resource that in the case of this example will abstract the details of opening a file for reading content.
-
-
- Fragment Deserializer - this is the UnMarshalling facility provided by Spring OXM for mapping the XML fragment to an object.
-
-
-
-
- <property name="itemReader">
+
+ Root Element Name - this is name of the root element of the
+ fragment that constitutes the object to be mapped. The example
+ configuration demonstrates this with the value of trade.
+
+
+
+ Resource - This is a Spring Resource that in the case of this
+ example will abstract the details of opening a file for reading
+ content.
+
+
+
+ Fragment Deserializer - this is the UnMarshalling facility
+ provided by Spring OXM for mapping the XML fragment to an
+ object.
+
+
+
+ <property name="itemReader">
<bean class="org.springframework.batch.io.xml.StaxEventItemReader">
<property name="fragmentRootElementName" value="trade" />
<property name="resource" value="data/staxJob/input/20070918.testStream.xmlFileStep.xml" />
@@ -970,18 +884,17 @@ FOT;2;2;267.34
</property>
</bean>
</property>
-
-
+
- Notice that it requires an alias passed in as a map with the
- first key and value being the name of the fragment and the object
- type that it will be mapped. Then, similar to a FieldSet, the
- names of the other elements that map to fields within the object
- type are described as key/value pairs in the map. In the
- configuration file we can use a spring configuration utility to
- described the required alias as follows:
-
-
+ Notice that in this example we have chosen to use an
+ XStreamMarshaller that requires an alias passed in as a map with the first
+ key and value being the name of the fragment (i.e. root element) and the
+ object type to bind. Then, similar to a FieldSet, the names of the other
+ elements that map to fields within the object type are described as
+ key/value pairs in the map. In the configuration file we can use a spring
+ configuration utility to describe the required alias as follows:
+
+
<util:map id="aliases">
<entry key="trade"
value="org.springframework.batch.sample.domain.Trade" />
@@ -990,49 +903,49 @@ FOT;2;2;267.34
<entry key="price" value="java.math.BigDecimal" />
<entry key="customer" value="java.lang.String" />
</util:map>
-
-
+
On input the reader reads the XML resource until it recognizes a new
fragment is about to start (by matching the tag name by default). The
reader creates a standalone XML document from the fragment (or at least
makes it appear so) and passes the document to a deserializer (typically a
- wrapper around Spring WS Unmarshaller) to map the XML to a Java
+ wrapper around a Spring WS Unmarshaller) to map the XML to a Java
object.
-
- In summary, if you were to see this in scripted code like Java the injection provided by the spring configuration would look something like the following:
-
-
-
- def xmlStaxEventItemReader = new StaxEventItemReader()
- resource = new ByteArrayResource(xmlResource.getBytes())
+ In summary, if you were to see this in scripted code like Java the
+ injection provided by the spring configuration would look something like
+ the following:
- def aliases = ["trade":"org.springframework.batch.sample.domain.Trade",
- "isin":"java.lang.String",
- "quantity":"long",
- "price":"java.math.BigDecimal",
- "customer":"java.lang.String"]
- def marshaller = new XStreamMarshaller()
- marshaller.setAliases(aliases)
- xmlStaxEventItemReader.setFragmentDeserializer(new UnmarshallingEventReaderDeserializer(marshaller))
- xmlStaxEventItemReader.setResource(resource)
- xmlStaxEventItemReader.setFragmentRootElementName("trade")
- def executionContext = new ExecutionContext()
- xmlStaxEventItemReader.open(executionContext);
+
+ StaxEventItemReader xmlStaxEventItemReader = new StaxEventItemReader()
+ Resource resource = new ByteArrayResource(xmlResource.getBytes())
- def hasNext = true
+ Map aliases = new HashMap();
+ aliases.put("trade","org.springframework.batch.sample.domain.Trade");
+ aliases.put("isin","java.lang.String");
+ aliases.put("quantity","long");
+ aliases.put("price","java.math.BigDecimal");
+ aliases.put("customer","java.lang.String");
+ Marshaller marshaller = new XStreamMarshaller();
+ marshaller.setAliases(aliases);
+ xmlStaxEventItemReader.setFragmentDeserializer(new UnmarshallingEventReaderDeserializer(marshaller));
+ xmlStaxEventItemReader.setResource(resource);
+ xmlStaxEventItemReader.setFragmentRootElementName("trade");
+ xmlStaxEventItemReader.open(new ExecutionContext());
+
+ boolean hasNext = true
+
while (hasNext) {
- trade = xmlStaxEventItemReader.read()
+ trade = xmlStaxEventItemReader.read();
if (trade == null) {
- hasNext = false
+ hasNext = false;
} else {
- println trade
+ println trade;
}
}
-
-
+
+
Output works symetrically to input. Java object is passed to a
serializer (typically a wrapper around Spring WS Marshaller) which writes
to output using a custom event writer that filters the StartDocument and
@@ -1041,6 +954,18 @@ FOT;2;2;267.34
For example configuration of XML input and output see the sample
xmlStaxJob. //TODO inline the example once it is not subject to change +
show sample input file
+
+
+ StaxEventItemReader
+
+
+
+
+
+ StaxEventItemWriter
+
+
+
@@ -1079,4 +1004,59 @@ FOT;2;2;267.34
-
+
+
+ Creating Custom ItemReaders and ItemWriters
+
+
+ The ListItemReader, as mentioned
+ above, is useful for testing and probably not too useful as something used
+ in typical batch processing. One instructive use is to see how narrow the
+ responsiblity of ItemReaders are. They simply provide a method that allows
+ us to continue reading items until the items are exhausted much like an
+ iterator. In addition,, it is expected that projects will create custom
+ Item Readers. As a means of illustrating the standard properties and
+ behaviors of other framework-provided ItemReaders like mapping
+ unstructured items into objects through the use of tokenizing we will
+ extend the ListItemReader to supporting mapping. The ItemReader interface
+ defines a single method called read().
+ The read() method returns the next object
+ to be provided, much like an iterator. The definition of this method will
+ contain the logic that decides what object to return, performs any object
+ construction or other work that needs to occur, and finally returns the
+ object. We inherit this behavior from ListItemReader. We will add two
+ methods, setFieldSetMapper(), to enable
+ the mapping behavior and setTokenizer(),
+ to enabling parsing of List Items. It this example the items in the list
+ are a simple array of delimited strings..
+
+ Here is our custom list item Reader that supplies mapping or binding
+ behavior as follows:
+ protected static class ListPlayerReader extends ListItemReader {
+ private FieldSetMapper fieldSetMapper;
+ private LineTokenizer tokenizer = null;
+
+ public ListPlayerReader(List list) {
+ super(list);
+ }
+
+ public void setFieldSetMapper(FieldSetMapper fieldSetMapper) {
+ this.fieldSetMapper = fieldSetMapper;
+ }
+
+ public void setTokenizer(LineTokenizer tokenizer) {
+ this.tokenizer = tokenizer;
+ }
+
+
+ }
+
+
+ We will tag it as an Player Reader for reasons you'll see next as we
+ map Player objects from input strings. In this example we have inherited
+ the read() behavior that allows us to read from a List in memory and
+ provided a way to map arbitrary streams into objects and added the ability
+ to map FieldSets to objects. We will see how to take advantage of this
+ next.
+
+
\ No newline at end of file