From 7f64b5c39ef41b11f2fedf3d9b645f324173be43 Mon Sep 17 00:00:00 2001 From: lucasward Date: Wed, 19 Mar 2008 23:39:11 +0000 Subject: [PATCH] BATCH-484: added documentation for ItemTransformerItemWriter, ItemTransformer, and CompsiteItemTransformer. --- .../docbook/reference/readersAndWriters.xml | 187 ++++++++++++++++++ 1 file changed, 187 insertions(+) diff --git a/docs/src/site/docbook/reference/readersAndWriters.xml b/docs/src/site/docbook/reference/readersAndWriters.xml index 51c695790..64f36a6d0 100644 --- a/docs/src/site/docbook/reference/readersAndWriters.xml +++ b/docs/src/site/docbook/reference/readersAndWriters.xml @@ -1729,6 +1729,193 @@ itemReader.close(executionContext); +
+ Item Transforming + + The ItemReader and + ItemWriter interfaces have been discussed in detail + in this chapter, but what if you want to insert business logic before + writing? One option for both reading and writing is to use the composite + pattern. That is, create an ItemWriter that + contains another ItemWriter, or an + ItemReader that contains another + ItemReader. For example: + + public class CompositeItemWriter implements ItemWriter { + + ItemWriter itemWriter; + + public CompositeItemWriter(ItemWriter itemWriter) { + this.itemWriter = itemWriter; + } + + public void write(Object item) throws Exception { + + //Add business logic here + + itemWriter.write(item); + } + + public void clear() throws ClearFailedException { + itemWriter.clear(); + } + + public void flush() throws FlushFailedException { + itemWriter.flush(); + } +} + + The class above contains another ItemWriter + that it delgates to after having provided some business logic. It should + be noted that the clear and + flush methods must be propogated as well so that + the delegate ItemWriter is notified. This pattern + could easily be used for an ItemReader as well, + perhaps to obtain more reference data based upon the input that was + provided by the main ItemReader. This pattern is + very useful if you need to control the call to + write yourself. However, if you only want to + 'transform' the item passed in for writing before it is actual written, + there isn't much need to call write yourself, you + just want to modify the item. For this scenario, Spring Batch provides the + ItemTransformer interface: + + public interface ItemTransformer { + + Object transform(Object item) throws Exception; + } + + An ItemTransformer interface is very simple, given one object, + transorm it and return another. The object provided may or may not be of + the same type. The point is that business logic may be applied within + transform, and is completely up to the developer to create. An + ItemTransformer is used as part of the + ItemTransformerItemWriter, which accepts an + ItemWriter and an + ItemTransformer, passing the item first to the + transformer, before writing it. For example, assuming an + ItemReader provides a class of type Foo, and it + needs to be converted to type Bar before being written out. An + ItemTransformer can be written that perform the + conversion: + + public class Foo {} + + public class Bar { + public Bar(Foo foo) {} + } + + public class FooTransformer implements ItemTransformer{ + + //Preform simple transformation, convert a Foo to a Barr + public Object transform(Object item) throws Exception { + assertTrue(item instanceof Foo); + Foo foo = (Foo)item; + return new Bar(foo); + } + } + + public class BarWriter implements ItemWriter{ + + public void write(Object item) throws Exception { + assertTrue(item instanceof Bar); + } + + //rest of class ommitted for clarity + } + + In the very simple example above, there is a class + Foo, a class Bar, and a + class FooTransformer that adheres to the + ItemTransformer interface. The transformation is + simple, but any type of transformation could be done here. The + BarWriter will be used to write out 'Bars', + throwing an exception if any other type is provided. Similarly, the + FooTransformer will throw an exception if anything but a + Foo is provided. An + ItemTransformerItemWriter can then be used like a + normal ItemWriter. It will be passed a Foo for + writing, which will be passed to the transformer, and a + Bar returned. The resulting + Bar will then be written: + + ItemTransformerItemWriter itemTransformerItemWriter = new ItemTransformerItemWriter(); + itemTransformerItemWriter.setItemTransformer(new FooTransformer()); + itemTransformerItemWriter.setDelegate(new BarWriter()); + itemTransformerItemWriter.write(new Foo()); + +
+ Chaining ItemTransformers + + Performing a single transformation is useful in many scenarios, + but what if you want to 'chain' together multiple ItemTransformers? This + can be accomplished using a + CompositeItemTransformer. To update the previous, + single transformation, example, Foo will be + Transformed to Bar, which will be transformed to + Foobar and written out: + + public class Foo {} + + public class Bar { + public Bar(Foo foo) {} + } + + public class Foobar{ + public Foobar(Bar bar){} + } + + public class FooTransformer implements ItemTransformer{ + + //Preform simple transformation, convert a Foo to a Barr + public Object transform(Object item) throws Exception { + assertTrue(item instanceof Foo); + Foo foo = (Foo)item; + return new Bar(foo); + } + } + + public class BarTransformer implements ItemTransformer{ + + public Object transform(Object item) throws Exception { + assertTrue(item instanceof Bar); + return new Foobar((Bar)item); + } + } + + public class FoobarWriter implements ItemWriter{ + + public void write(Object item) throws Exception { + assertTrue(item instanceof Foobar); + } + + //rest of class ommitted for clarity + } + + A FooTransformer and + BarTransformer can be 'chained' together to give + the resultant Foobar: + + CompositeItemTransformer compositeTransformer = new CompositeItemTransformer(); + List itemTransformers = new ArrayList(); + itemTransformers.add(new FooTransformer()); + itemTransformers.add(new BarTransformer()); + compositeTransformer.setItemTransformers(itemTransformers); + + The compositeTransformer could be said to accept a + Foo and return a Foobar. + Clients of the composite transformer don't need to know that there are + actually two separate transformations taking place. By updating the + example from above to use the composite transformer, the correct class + can be passed to FoobarWriter: + + ItemTransformerItemWriter itemTransformerItemWriter = new ItemTransformerItemWriter(); + itemTransformerItemWriter.setItemTransformer(compositeTransformer); + itemTransformerItemWriter.setDelegate(new FoobarWriter()); + itemTransformerItemWriter.write(new Foo()); +
+
+
Validating Input