From fa35c229f213dfdc0e4e99c2b63eab686df1a85f Mon Sep 17 00:00:00 2001 From: lucasward Date: Wed, 26 Sep 2007 00:37:43 +0000 Subject: [PATCH] OPEN - issue BATCH-116: Create XML input/output source which will work directly with StAX parser http://opensource.atlassian.com/projects/spring/browse/BATCH-116 Added additional code coverage to infrastructure, validation to samples jobs, and integration tests for castor and xstream --- integration/pom.xml | 44 ++++++++++- ...stractStaxEventReaderInputSourceTests.java | 79 +++++++++++++++++++ ...tractStaxEventWriterOutputSourceTests.java | 73 +++++++++++++++++ .../batch/io/oxm/CastorMarshallingTests.java | 20 +++++ .../io/oxm/CastorUnmarshallingTests.java | 18 +++++ .../batch/io/oxm/XStreamMarshallingTests.java | 18 +++++ .../io/oxm/XStreamUnmarshallingTests.java | 20 +++++ .../batch/io/oxm/domain/Trade.java | 72 +++++++++++++++++ .../batch/io/oxm/expected-output.xml | 24 ++++++ .../springframework/batch/io/oxm/input.xml | 21 +++++ .../batch/io/oxm/mapping-castor.xml | 23 ++++++ 11 files changed, 411 insertions(+), 1 deletion(-) create mode 100644 integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventReaderInputSourceTests.java create mode 100644 integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventWriterOutputSourceTests.java create mode 100644 integration/src/test/java/org/springframework/batch/io/oxm/CastorMarshallingTests.java create mode 100644 integration/src/test/java/org/springframework/batch/io/oxm/CastorUnmarshallingTests.java create mode 100644 integration/src/test/java/org/springframework/batch/io/oxm/XStreamMarshallingTests.java create mode 100644 integration/src/test/java/org/springframework/batch/io/oxm/XStreamUnmarshallingTests.java create mode 100644 integration/src/test/java/org/springframework/batch/io/oxm/domain/Trade.java create mode 100644 integration/src/test/resources/org/springframework/batch/io/oxm/expected-output.xml create mode 100644 integration/src/test/resources/org/springframework/batch/io/oxm/input.xml create mode 100644 integration/src/test/resources/org/springframework/batch/io/oxm/mapping-castor.xml diff --git a/integration/pom.xml b/integration/pom.xml index 9b341c5a1..f7bb58fb4 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -19,7 +19,7 @@ - true + true @@ -92,6 +92,48 @@ + + xmlunit + xmlunit + 1.1 + test + true + + + org.springframework.ws + spring-oxm + 1.0.0 + test + true + + + org.springframework + spring-beans + + + org.springframework + spring-core + + + + + org.codehaus.castor + castor + 1.1.2 + test + true + + + stax + stax + true + + + com.thoughtworks.xstream + xstream + 1.2.1 + true + diff --git a/integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventReaderInputSourceTests.java b/integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventReaderInputSourceTests.java new file mode 100644 index 000000000..9b3879227 --- /dev/null +++ b/integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventReaderInputSourceTests.java @@ -0,0 +1,79 @@ +package org.springframework.batch.io.oxm; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.springframework.batch.io.oxm.domain.Trade; +import org.springframework.batch.io.stax.StaxEventReaderInputSource; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.oxm.Unmarshaller; + +public abstract class AbstractStaxEventReaderInputSourceTests extends TestCase { + + private StaxEventReaderInputSource source = new StaxEventReaderInputSource(); + + protected Resource resource = new ClassPathResource( + "org/springframework/batch/io/oxm/input.xml"); + + + protected void setUp() throws Exception { + //TODO sensible resource allocation + source.setResource(resource); + + source.setFragmentRootElementName("trade"); + UnmarshallingFragmentDeserializer deserializer = new UnmarshallingFragmentDeserializer(getUnmarshaller()); + source.setFragmentDeserializer(deserializer); + } + + public void testRead() { + Object result; + List results = new ArrayList(); + while ((result = source.read()) != null) { + results.add(result); + } + checkResults(results); + + } + + /** + * @return Unmarshaller specific to the OXM library used + */ + protected abstract Unmarshaller getUnmarshaller() throws Exception; + + /** + * @param results list of domain objects returned by input source + */ + protected void checkResults(List results){ + assertEquals(3, results.size()); + + Trade trade1 = (Trade) results.get(0); + assertEquals("XYZ0001", trade1.getIsin()); + assertEquals(5, trade1.getQuantity()); + assertEquals(BigDecimal.valueOf(11.39), trade1.getPrice()); + assertEquals("Customer1", trade1.getCustomer()); + + Trade trade2 = (Trade) results.get(1); + assertEquals("XYZ0002", trade2.getIsin()); + assertEquals(2, trade2.getQuantity()); + assertEquals(BigDecimal.valueOf(72.99), trade2.getPrice()); + assertEquals("Customer2", trade2.getCustomer()); + + Trade trade3 = (Trade) results.get(2); + assertEquals("XYZ0003", trade3.getIsin()); + assertEquals(9, trade3.getQuantity()); + assertEquals(BigDecimal.valueOf(99.99), trade3.getPrice()); + assertEquals("Customer3", trade3.getCustomer()); + } + + protected void tearDown() throws Exception { + source.close(); + } + + public void setResource(Resource resource) { + this.resource = resource; + } +} diff --git a/integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventWriterOutputSourceTests.java b/integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventWriterOutputSourceTests.java new file mode 100644 index 000000000..fbd282ba2 --- /dev/null +++ b/integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventWriterOutputSourceTests.java @@ -0,0 +1,73 @@ +package org.springframework.batch.io.oxm; + +import java.io.File; +import java.io.FileReader; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import junit.framework.TestCase; + +import org.custommonkey.xmlunit.XMLAssert; +import org.custommonkey.xmlunit.XMLUnit; +import org.springframework.batch.io.oxm.domain.Trade; +import org.springframework.batch.io.stax.StaxEventWriterOutputSource; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.oxm.Marshaller; + +public abstract class AbstractStaxEventWriterOutputSourceTests extends TestCase { + + private StaxEventWriterOutputSource source = new StaxEventWriterOutputSource(); + + private Resource resource; + + File outputFile; + + protected Resource expected = new ClassPathResource("expected-output.xml", getClass()); + + + protected List objects = new ArrayList() {{ + add(new Trade("isin1", 1, new BigDecimal(1.0), "customer1")); + add(new Trade("isin2", 2, new BigDecimal(2.0), "customer2")); + add(new Trade("isin3", 3, new BigDecimal(3.0), "customer3")); + }}; + + /** + * Write list of domain objects and check the output file. + */ + public void testWrite() throws Exception { + for (Iterator iterator = objects.listIterator(); iterator.hasNext();) { + source.write(iterator.next()); + } + source.close(); + XMLUnit.setIgnoreWhitespace(true); + XMLAssert.assertXMLEqual(new FileReader(expected.getFile()), new FileReader(resource.getFile())); + + } + + + protected void setUp() throws Exception { + //File outputFile = File.createTempFile("AbstractStaxStreamWriterOutputSourceTests", "xml"); + outputFile = File.createTempFile(this.getClass().getSimpleName(), ".xml"); + resource = new FileSystemResource(outputFile); + source.setResource(resource); + + MarshallingObjectToXmlSerializer mapper = new MarshallingObjectToXmlSerializer(getMarshaller()); + source.setSerializer(mapper); + } + + protected void tearDown() throws Exception { + super.tearDown(); + + outputFile.delete(); + } + + /** + * @return Marshaller specific for the OXM technology being used. + */ + protected abstract Marshaller getMarshaller() throws Exception; + +} diff --git a/integration/src/test/java/org/springframework/batch/io/oxm/CastorMarshallingTests.java b/integration/src/test/java/org/springframework/batch/io/oxm/CastorMarshallingTests.java new file mode 100644 index 000000000..3877246b3 --- /dev/null +++ b/integration/src/test/java/org/springframework/batch/io/oxm/CastorMarshallingTests.java @@ -0,0 +1,20 @@ +package org.springframework.batch.io.oxm; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.castor.CastorMarshaller; + +public class CastorMarshallingTests extends AbstractStaxEventWriterOutputSourceTests { + + protected Marshaller getMarshaller() throws Exception { + + CastorMarshaller marshaller = new CastorMarshaller(); + // marshaller.setTargetClass(Trade.class); + marshaller.setMappingLocation(new ClassPathResource("mapping-castor.xml", getClass())); + // there is no way to call + // org.exolab.castor.xml.Marshaller.setSupressXMLDeclaration(); + marshaller.afterPropertiesSet(); + return marshaller; + } + +} diff --git a/integration/src/test/java/org/springframework/batch/io/oxm/CastorUnmarshallingTests.java b/integration/src/test/java/org/springframework/batch/io/oxm/CastorUnmarshallingTests.java new file mode 100644 index 000000000..25ba7efee --- /dev/null +++ b/integration/src/test/java/org/springframework/batch/io/oxm/CastorUnmarshallingTests.java @@ -0,0 +1,18 @@ +package org.springframework.batch.io.oxm; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.oxm.Unmarshaller; +import org.springframework.oxm.castor.CastorMarshaller; + +public class CastorUnmarshallingTests extends AbstractStaxEventReaderInputSourceTests { + + protected Unmarshaller getUnmarshaller() throws Exception { + CastorMarshaller unmarshaller = new CastorMarshaller(); + unmarshaller.setMappingLocation(new ClassPathResource("mapping-castor.xml", getClass())); + // alternatively target class can be set + //unmarshaller.setTargetClass(Trade.class); + unmarshaller.afterPropertiesSet(); + return unmarshaller; + } + +} diff --git a/integration/src/test/java/org/springframework/batch/io/oxm/XStreamMarshallingTests.java b/integration/src/test/java/org/springframework/batch/io/oxm/XStreamMarshallingTests.java new file mode 100644 index 000000000..6e8827b4a --- /dev/null +++ b/integration/src/test/java/org/springframework/batch/io/oxm/XStreamMarshallingTests.java @@ -0,0 +1,18 @@ +package org.springframework.batch.io.oxm; + +import org.springframework.batch.io.oxm.domain.Trade; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.xstream.XStreamMarshaller; + +public class XStreamMarshallingTests extends + AbstractStaxEventWriterOutputSourceTests { + + protected Marshaller getMarshaller() throws Exception { + XStreamMarshaller marshaller = new XStreamMarshaller(); + marshaller.addAlias("trade", Trade.class); + //in XStreamMarshaller.marshalSaxHandlers() method is used SaxWriter, which is configured + //to include enclosing document (SaxWriter.includeEnclosingDocument is always set to TRUE) + return marshaller; + } + +} diff --git a/integration/src/test/java/org/springframework/batch/io/oxm/XStreamUnmarshallingTests.java b/integration/src/test/java/org/springframework/batch/io/oxm/XStreamUnmarshallingTests.java new file mode 100644 index 000000000..89eeba3c1 --- /dev/null +++ b/integration/src/test/java/org/springframework/batch/io/oxm/XStreamUnmarshallingTests.java @@ -0,0 +1,20 @@ +package org.springframework.batch.io.oxm; + +import java.math.BigDecimal; + +import org.springframework.batch.io.oxm.domain.Trade; +import org.springframework.oxm.Unmarshaller; +import org.springframework.oxm.xstream.XStreamMarshaller; + +public class XStreamUnmarshallingTests extends AbstractStaxEventReaderInputSourceTests { + + protected Unmarshaller getUnmarshaller() throws Exception { + XStreamMarshaller unmarshaller = new XStreamMarshaller(); + unmarshaller.addAlias("trade", Trade.class); + unmarshaller.addAlias("isin", String.class); + unmarshaller.addAlias("customer", String.class); + unmarshaller.addAlias("price", BigDecimal.class); + return unmarshaller; + } + +} diff --git a/integration/src/test/java/org/springframework/batch/io/oxm/domain/Trade.java b/integration/src/test/java/org/springframework/batch/io/oxm/domain/Trade.java new file mode 100644 index 000000000..bc959b60f --- /dev/null +++ b/integration/src/test/java/org/springframework/batch/io/oxm/domain/Trade.java @@ -0,0 +1,72 @@ +package org.springframework.batch.io.oxm.domain; + +import java.math.BigDecimal; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + + +/** + * @author Rob Harrop + */ +public class Trade { + private String isin = ""; + private long quantity = 0; + private BigDecimal price = new BigDecimal(0); + private String customer = ""; + + public Trade() { + } + + public Trade(String isin, long quantity, BigDecimal price, String customer){ + this.isin = isin; + this.quantity = quantity; + this.price = price; + this.customer = customer; + } + + public void setCustomer(String customer) { + this.customer = customer; + } + + public void setIsin(String isin) { + this.isin = isin; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + public void setQuantity(long quantity) { + this.quantity = quantity; + } + + public String getIsin() { + return isin; + } + + public BigDecimal getPrice() { + return price; + } + + public long getQuantity() { + return quantity; + } + + public String getCustomer() { + return customer; + } + + public String toString() { + return "Trade: [isin=" + this.isin + ",quantity=" + this.quantity + ",price=" + + this.price + ",customer=" + this.customer + "]"; + } + + public boolean equals(Object o) { + return EqualsBuilder.reflectionEquals(this, o); + } + + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } +} diff --git a/integration/src/test/resources/org/springframework/batch/io/oxm/expected-output.xml b/integration/src/test/resources/org/springframework/batch/io/oxm/expected-output.xml new file mode 100644 index 000000000..d0644b0c4 --- /dev/null +++ b/integration/src/test/resources/org/springframework/batch/io/oxm/expected-output.xml @@ -0,0 +1,24 @@ + + + + isin1 + 1 + 1 + customer1 + + + + isin2 + 2 + 2 + customer2 + + + + isin3 + 3 + 3 + customer3 + + + \ No newline at end of file diff --git a/integration/src/test/resources/org/springframework/batch/io/oxm/input.xml b/integration/src/test/resources/org/springframework/batch/io/oxm/input.xml new file mode 100644 index 000000000..0e76751a4 --- /dev/null +++ b/integration/src/test/resources/org/springframework/batch/io/oxm/input.xml @@ -0,0 +1,21 @@ + + + + XYZ0001 + 5 + 11.39 + Customer1 + + + XYZ0002 + 2 + 72.99 + Customer2 + + + XYZ0003 + 9 + 99.99 + Customer3 + + diff --git a/integration/src/test/resources/org/springframework/batch/io/oxm/mapping-castor.xml b/integration/src/test/resources/org/springframework/batch/io/oxm/mapping-castor.xml new file mode 100644 index 000000000..b9306dbee --- /dev/null +++ b/integration/src/test/resources/org/springframework/batch/io/oxm/mapping-castor.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file