RESOLVED - issue BATCH-1430: StaxEventItemWriter: Declare additional namespaces at the top-level element
This commit is contained in:
@@ -123,7 +123,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ws</groupId>
|
||||
<artifactId>spring-oxm</artifactId>
|
||||
<artifactId>spring-oxm-tiger</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package org.springframework.batch.io.oxm;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.batch.io.oxm.domain.Trade;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.xml.StaxEventItemReader;
|
||||
@@ -13,28 +16,32 @@ import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.oxm.Unmarshaller;
|
||||
|
||||
public abstract class AbstractStaxEventReaderItemReaderTests extends TestCase {
|
||||
public abstract class AbstractStaxEventReaderItemReaderTests {
|
||||
|
||||
private StaxEventItemReader<Trade> source = new StaxEventItemReader<Trade>();
|
||||
protected StaxEventItemReader<Trade> reader = new StaxEventItemReader<Trade>();
|
||||
|
||||
protected Resource resource = new ClassPathResource("org/springframework/batch/io/oxm/input.xml");
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
source.setResource(resource);
|
||||
reader.setResource(resource);
|
||||
|
||||
source.setFragmentRootElementName("trade");
|
||||
reader.setFragmentRootElementName("trade");
|
||||
|
||||
source.setUnmarshaller(getUnmarshaller());
|
||||
reader.setUnmarshaller(getUnmarshaller());
|
||||
|
||||
source.open(new ExecutionContext());
|
||||
reader.afterPropertiesSet();
|
||||
|
||||
reader.open(new ExecutionContext());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRead() throws Exception {
|
||||
Trade result;
|
||||
List<Trade> results = new ArrayList<Trade>();
|
||||
while ((result = source.read()) != null) {
|
||||
while ((result = reader.read()) != null) {
|
||||
results.add(result);
|
||||
}
|
||||
checkResults(results);
|
||||
@@ -71,8 +78,9 @@ public abstract class AbstractStaxEventReaderItemReaderTests extends TestCase {
|
||||
assertEquals("Customer3", trade3.getCustomer());
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
source.close();
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
reader.close();
|
||||
}
|
||||
|
||||
public void setResource(Resource resource) {
|
||||
|
||||
@@ -33,11 +33,11 @@ public abstract class AbstractStaxEventWriterItemWriterTests {
|
||||
|
||||
private static final int MAX_WRITE = 100;
|
||||
|
||||
private StaxEventItemWriter<Trade> writer = new StaxEventItemWriter<Trade>();
|
||||
protected StaxEventItemWriter<Trade> writer = new StaxEventItemWriter<Trade>();
|
||||
|
||||
private Resource resource;
|
||||
|
||||
File outputFile;
|
||||
private File outputFile;
|
||||
|
||||
protected Resource expected = new ClassPathResource("expected-output.xml", getClass());
|
||||
|
||||
@@ -62,8 +62,11 @@ public abstract class AbstractStaxEventWriterItemWriterTests {
|
||||
try {
|
||||
writer.write(objects);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
status.setRollbackOnly();
|
||||
throw new IllegalStateException("Exception encountered on write", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -73,22 +76,26 @@ public abstract class AbstractStaxEventWriterItemWriterTests {
|
||||
stopWatch.stop();
|
||||
logger.info("Timing for XML writer: " + stopWatch);
|
||||
XMLUnit.setIgnoreWhitespace(true);
|
||||
// String content = FileUtils.readFileToString(resource.getFile());
|
||||
// System.err.println(content);
|
||||
XMLAssert.assertXMLEqual(new FileReader(expected.getFile()), new FileReader(resource.getFile()));
|
||||
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
// File outputFile =
|
||||
// File.createTempFile("AbstractStaxStreamWriterOutputSourceTests",
|
||||
// "xml");
|
||||
outputFile = File.createTempFile(ClassUtils.getShortName(this.getClass()), ".xml");
|
||||
|
||||
File directory = new File("target/data");
|
||||
directory.mkdirs();
|
||||
outputFile = File.createTempFile(ClassUtils.getShortName(this.getClass()), ".xml", directory);
|
||||
resource = new FileSystemResource(outputFile);
|
||||
writer.setResource(resource);
|
||||
|
||||
writer.setMarshaller(getMarshaller());
|
||||
writer.afterPropertiesSet();
|
||||
|
||||
writer.open(new ExecutionContext());
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.springframework.batch.io.oxm;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.springframework.batch.io.oxm.domain.Trade;
|
||||
import org.springframework.oxm.Marshaller;
|
||||
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
|
||||
|
||||
public class Jaxb2MarshallingTests extends AbstractStaxEventWriterItemWriterTests {
|
||||
|
||||
protected Marshaller getMarshaller() throws Exception {
|
||||
|
||||
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setClassesToBeBound(new Class<?>[] { Trade.class });
|
||||
marshaller.afterPropertiesSet();
|
||||
|
||||
StringWriter string = new StringWriter();
|
||||
marshaller.marshal(new Trade("FOO", 100, BigDecimal.valueOf(10.), "bar"), new StreamResult(string));
|
||||
String content = string.toString();
|
||||
assertTrue("Wrong content: "+content, content.contains("<customer>bar</customer>"));
|
||||
return marshaller;
|
||||
}
|
||||
|
||||
public static String getTextFromSource(Source source) {
|
||||
try {
|
||||
Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
StreamResult stream = new StreamResult(new StringWriter());
|
||||
transformer.transform(source, stream);
|
||||
return stream.getWriter().toString();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package org.springframework.batch.io.oxm;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.StringWriter;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.custommonkey.xmlunit.XMLAssert;
|
||||
import org.custommonkey.xmlunit.XMLUnit;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.batch.io.oxm.domain.QualifiedTrade;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.xml.StaxEventItemWriter;
|
||||
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.oxm.Marshaller;
|
||||
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
public class Jaxb2NamespaceMarshallingTests {
|
||||
|
||||
private Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private static final int MAX_WRITE = 100;
|
||||
|
||||
private StaxEventItemWriter<QualifiedTrade> writer = new StaxEventItemWriter<QualifiedTrade>();
|
||||
|
||||
private Resource resource;
|
||||
|
||||
private File outputFile;
|
||||
|
||||
private Resource expected = new ClassPathResource("expected-qualified-output.xml", getClass());
|
||||
|
||||
private List<QualifiedTrade> objects = new ArrayList<QualifiedTrade>() {
|
||||
{
|
||||
add(new QualifiedTrade("isin1", 1, new BigDecimal(1.0), "customer1"));
|
||||
add(new QualifiedTrade("isin2", 2, new BigDecimal(2.0), "customer2"));
|
||||
add(new QualifiedTrade("isin3", 3, new BigDecimal(3.0), "customer3"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Write list of domain objects and check the output file.
|
||||
*/
|
||||
@Test
|
||||
public void testWrite() throws Exception {
|
||||
StopWatch stopWatch = new StopWatch(getClass().getSimpleName());
|
||||
stopWatch.start();
|
||||
for (int i = 0; i < MAX_WRITE; i++) {
|
||||
new TransactionTemplate(new ResourcelessTransactionManager()).execute(new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
try {
|
||||
writer.write(objects);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException("Exception encountered on write", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
writer.close();
|
||||
stopWatch.stop();
|
||||
logger.info("Timing for XML writer: " + stopWatch);
|
||||
XMLUnit.setIgnoreWhitespace(true);
|
||||
// String content = FileUtils.readFileToString(resource.getFile());
|
||||
// System.err.println(content);
|
||||
XMLAssert.assertXMLEqual(new FileReader(expected.getFile()), new FileReader(resource.getFile()));
|
||||
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
File directory = new File("target/data");
|
||||
directory.mkdirs();
|
||||
outputFile = File.createTempFile(ClassUtils.getShortName(this.getClass()), ".xml", directory);
|
||||
resource = new FileSystemResource(outputFile);
|
||||
|
||||
writer.setResource(resource);
|
||||
|
||||
writer.setMarshaller(getMarshaller());
|
||||
writer.setRootTagName("{urn:org.springframework.batch.io.oxm.domain}trades");
|
||||
|
||||
writer.afterPropertiesSet();
|
||||
|
||||
writer.open(new ExecutionContext());
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
outputFile.delete();
|
||||
}
|
||||
|
||||
protected Marshaller getMarshaller() throws Exception {
|
||||
|
||||
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setClassesToBeBound(new Class<?>[] { QualifiedTrade.class });
|
||||
marshaller.afterPropertiesSet();
|
||||
|
||||
StringWriter string = new StringWriter();
|
||||
marshaller.marshal(new QualifiedTrade("FOO", 100, BigDecimal.valueOf(10.), "bar"), new StreamResult(string));
|
||||
String content = string.toString();
|
||||
assertTrue("Wrong content: "+content, content.contains("<customer>bar</customer>"));
|
||||
return marshaller;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package org.springframework.batch.io.oxm;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.batch.io.oxm.domain.QualifiedTrade;
|
||||
import org.springframework.batch.io.oxm.domain.Trade;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.xml.StaxEventItemReader;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.oxm.Unmarshaller;
|
||||
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
|
||||
|
||||
public class Jaxb2NamespaceUnmarshallingTests {
|
||||
|
||||
private StaxEventItemReader<QualifiedTrade> reader = new StaxEventItemReader<QualifiedTrade>();
|
||||
|
||||
private Resource resource = new ClassPathResource("org/springframework/batch/io/oxm/domain/trades.xml");
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
reader.setResource(resource);
|
||||
|
||||
reader.setFragmentRootElementName("{urn:org.springframework.batch.io.oxm.domain}trade");
|
||||
|
||||
reader.setUnmarshaller(getUnmarshaller());
|
||||
|
||||
reader.afterPropertiesSet();
|
||||
|
||||
reader.open(new ExecutionContext());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnmarshal() throws Exception {
|
||||
QualifiedTrade trade = (QualifiedTrade) getUnmarshaller().unmarshal(new StreamSource(new StringReader(TRADE_XML)));
|
||||
assertEquals("XYZ0001", trade.getIsin());
|
||||
assertEquals(5, trade.getQuantity());
|
||||
assertEquals(new BigDecimal("11.39"), trade.getPrice());
|
||||
assertEquals("Customer1", trade.getCustomer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRead() throws Exception {
|
||||
QualifiedTrade result;
|
||||
List<QualifiedTrade> results = new ArrayList<QualifiedTrade>();
|
||||
while ((result = reader.read()) != null) {
|
||||
results.add(result);
|
||||
}
|
||||
checkResults(results);
|
||||
|
||||
}
|
||||
|
||||
protected Unmarshaller getUnmarshaller() throws Exception {
|
||||
|
||||
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setClassesToBeBound(new Class<?>[] { QualifiedTrade.class });
|
||||
marshaller.setSchema(new ClassPathResource("trade.xsd", Trade.class));
|
||||
marshaller.afterPropertiesSet();
|
||||
|
||||
return marshaller;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param results list of domain objects returned by input source
|
||||
*/
|
||||
protected void checkResults(List<QualifiedTrade> results) {
|
||||
assertEquals(3, results.size());
|
||||
|
||||
QualifiedTrade trade1 = results.get(0);
|
||||
assertEquals("XYZ0001", trade1.getIsin());
|
||||
assertEquals(5, trade1.getQuantity());
|
||||
assertEquals(new BigDecimal("11.39"), trade1.getPrice());
|
||||
assertEquals("Customer1", trade1.getCustomer());
|
||||
|
||||
QualifiedTrade trade2 = results.get(1);
|
||||
assertEquals("XYZ0002", trade2.getIsin());
|
||||
assertEquals(2, trade2.getQuantity());
|
||||
assertEquals(new BigDecimal("72.99"), trade2.getPrice());
|
||||
assertEquals("Customer2", trade2.getCustomer());
|
||||
|
||||
QualifiedTrade trade3 = results.get(2);
|
||||
assertEquals("XYZ0003", trade3.getIsin());
|
||||
assertEquals(9, trade3.getQuantity());
|
||||
assertEquals(new BigDecimal("99.99"), trade3.getPrice());
|
||||
assertEquals("Customer3", trade3.getCustomer());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
reader.close();
|
||||
}
|
||||
|
||||
private static String TRADE_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><trade xmlns=\"urn:org.springframework.batch.io.oxm.domain\">"
|
||||
+ "<customer>Customer1</customer><isin>XYZ0001</isin><price>11.39</price><quantity>5</quantity>"
|
||||
+ "</trade>";
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.springframework.batch.io.oxm;
|
||||
|
||||
import org.springframework.batch.io.oxm.domain.Trade;
|
||||
import org.springframework.oxm.Unmarshaller;
|
||||
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
|
||||
|
||||
public class Jaxb2UnmarshallingTests extends AbstractStaxEventReaderItemReaderTests {
|
||||
|
||||
protected Unmarshaller getUnmarshaller() throws Exception {
|
||||
reader.setFragmentRootElementName("trade");
|
||||
|
||||
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setClassesToBeBound(new Class<?>[] { Trade.class });
|
||||
// marshaller.setSchema(new ClassPathResource("trade.xsd", Trade.class));
|
||||
marshaller.afterPropertiesSet();
|
||||
|
||||
return marshaller;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package org.springframework.batch.io.oxm.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
*/
|
||||
@XmlRootElement(name="trade", namespace="urn:org.springframework.batch.io.oxm.domain")
|
||||
@XmlType
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class QualifiedTrade {
|
||||
|
||||
@XmlElement(namespace="urn:org.springframework.batch.io.oxm.domain")
|
||||
private String isin = "";
|
||||
|
||||
@XmlElement(namespace="urn:org.springframework.batch.io.oxm.domain")
|
||||
private long quantity = 0;
|
||||
|
||||
@XmlElement(namespace="urn:org.springframework.batch.io.oxm.domain")
|
||||
private BigDecimal price = new BigDecimal(0);
|
||||
|
||||
@XmlElement(namespace="urn:org.springframework.batch.io.oxm.domain")
|
||||
private String customer = "";
|
||||
|
||||
public QualifiedTrade() {
|
||||
}
|
||||
|
||||
public QualifiedTrade(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 + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((customer == null) ? 0 : customer.hashCode());
|
||||
result = prime * result + ((isin == null) ? 0 : isin.hashCode());
|
||||
result = prime * result + ((price == null) ? 0 : price.hashCode());
|
||||
result = prime * result + (int) (quantity ^ (quantity >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
QualifiedTrade other = (QualifiedTrade) obj;
|
||||
if (customer == null) {
|
||||
if (other.customer != null)
|
||||
return false;
|
||||
}
|
||||
else if (!customer.equals(other.customer))
|
||||
return false;
|
||||
if (isin == null) {
|
||||
if (other.isin != null)
|
||||
return false;
|
||||
}
|
||||
else if (!isin.equals(other.isin))
|
||||
return false;
|
||||
if (price == null) {
|
||||
if (other.price != null)
|
||||
return false;
|
||||
}
|
||||
else if (!price.equals(other.price))
|
||||
return false;
|
||||
if (quantity != other.quantity)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,9 +2,14 @@ package org.springframework.batch.io.oxm.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
*/
|
||||
@XmlRootElement(name="trade")
|
||||
@XmlType
|
||||
public class Trade {
|
||||
private String isin = "";
|
||||
|
||||
|
||||
@@ -9,4 +9,5 @@ log4j.category.org.apache.activemq=ERROR
|
||||
log4j.category.org.springframework.jdbc=DEBUG
|
||||
log4j.category.org.springframework.jms=DEBUG
|
||||
log4j.category.org.springframework.batch=DEBUG
|
||||
log4j.category.org.springframework.batch.support=INFO
|
||||
log4j.category.org.springframework.retry=DEBUG
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<xs:schema version="1.0" targetNamespace="urn:org.springframework.batch.io.oxm.domain"
|
||||
xmlns:tns="urn:org.springframework.batch.io.oxm.domain" xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<xs:element name="trades">
|
||||
<xs:complexType>
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded"><xs:element name="trade" type="tns:trade"/></xs:choice>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<xs:element name="trade" type="tns:trade"/>
|
||||
|
||||
<xs:complexType name="trade">
|
||||
<xs:sequence>
|
||||
<xs:element name="customer" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="isin" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="price" type="xs:decimal" minOccurs="0"/>
|
||||
<xs:element name="quantity" type="xs:long"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
</xs:schema>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<trades xmlns="urn:org.springframework.batch.io.oxm.domain" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="urn:org.springframework.batch.io.oxm.domain trade.xsd">
|
||||
<trade>
|
||||
<customer>Customer1</customer>
|
||||
<isin>XYZ0001</isin>
|
||||
<price>11.39</price>
|
||||
<quantity>5</quantity>
|
||||
</trade>
|
||||
<trade>
|
||||
<customer>Customer2</customer>
|
||||
<isin>XYZ0002</isin>
|
||||
<price>72.99</price>
|
||||
<quantity>2</quantity>
|
||||
</trade>
|
||||
<trade>
|
||||
<customer>Customer3</customer>
|
||||
<isin>XYZ0003</isin>
|
||||
<price>99.99</price>
|
||||
<quantity>9</quantity>
|
||||
</trade>
|
||||
</trades>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -141,7 +141,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ws</groupId>
|
||||
<artifactId>spring-oxm</artifactId>
|
||||
<artifactId>spring-oxm-tiger</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -232,15 +232,17 @@ public class StaxEventItemWriter<T> extends ExecutionContextUserSupport implemen
|
||||
|
||||
/**
|
||||
* Set the tag name of the root element. If not set, default name is used
|
||||
* ("root"). Namespace URI and prefix can also be set optionally using the
|
||||
* ("root"). Namespace URI and prefix can also be set optionally using the
|
||||
* notation:
|
||||
*
|
||||
* <pre>
|
||||
* {uri}prefix:root
|
||||
* </pre>
|
||||
*
|
||||
* The prefix is optional (defaults to empty), but if it is specified then the
|
||||
* uri must be provided.
|
||||
* The prefix is optional (defaults to empty), but if it is specified then
|
||||
* the uri must be provided. In addition you might want to declare other
|
||||
* namespaces using the {@link #setRootElementAttributes(Map) root
|
||||
* attributes}.
|
||||
*
|
||||
* @param rootTagName the tag name to be used for the root element
|
||||
*/
|
||||
@@ -276,7 +278,8 @@ public class StaxEventItemWriter<T> extends ExecutionContextUserSupport implemen
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the root element attributes to be written.
|
||||
* Set the root element attributes to be written. If any of the key names
|
||||
* begin with "xmlns:" then they are treated as namespace declarations.
|
||||
*
|
||||
* @param rootElementAttributes attributes of the root element
|
||||
*/
|
||||
@@ -307,8 +310,7 @@ public class StaxEventItemWriter<T> extends ExecutionContextUserSupport implemen
|
||||
if (rootTagName.contains("{")) {
|
||||
rootTagNamespace = rootTagName.replaceAll("\\{(.*)\\}.*", "$1");
|
||||
rootTagName = rootTagName.replaceAll("\\{.*\\}(.*)", "$1");
|
||||
if (rootTagName.contains(":"))
|
||||
{
|
||||
if (rootTagName.contains(":")) {
|
||||
rootTagNamespacePrefix = rootTagName.replaceAll("(.*):.*", "$1");
|
||||
rootTagName = rootTagName.replaceAll(".*:(.*)", "$1");
|
||||
}
|
||||
@@ -430,14 +432,29 @@ public class StaxEventItemWriter<T> extends ExecutionContextUserSupport implemen
|
||||
// write root tag
|
||||
writer.add(factory.createStartElement(getRootTagNamespacePrefix(), getRootTagNamespace(), getRootTagName()));
|
||||
if (StringUtils.hasText(getRootTagNamespace())) {
|
||||
writer.add(factory.createNamespace(getRootTagNamespacePrefix(), getRootTagNamespace()));
|
||||
if (StringUtils.hasText(getRootTagNamespacePrefix())) {
|
||||
writer.add(factory.createNamespace(getRootTagNamespacePrefix(), getRootTagNamespace()));
|
||||
}
|
||||
else {
|
||||
writer.add(factory.createNamespace(getRootTagNamespace()));
|
||||
}
|
||||
}
|
||||
|
||||
// write root tag attributes
|
||||
if (!CollectionUtils.isEmpty(getRootElementAttributes())) {
|
||||
|
||||
for (Map.Entry<String, String> entry : getRootElementAttributes().entrySet()) {
|
||||
writer.add(factory.createAttribute(entry.getKey(), entry.getValue()));
|
||||
String key = entry.getKey();
|
||||
if (key.startsWith("xmlns")) {
|
||||
String prefix = "";
|
||||
if (key.contains(":")) {
|
||||
prefix = key.substring(key.indexOf(":") + 1);
|
||||
}
|
||||
writer.add(factory.createNamespace(prefix, entry.getValue()));
|
||||
}
|
||||
else {
|
||||
writer.add(factory.createAttribute(key, entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -62,9 +62,19 @@ public class StaxEventItemWriterTests {
|
||||
private static final String TEST_STRING = "<" + ClassUtils.getShortName(StaxEventItemWriter.class)
|
||||
+ "-testString/>";
|
||||
|
||||
private static final String NS_TEST_STRING = "<ns:" + ClassUtils.getShortName(StaxEventItemWriter.class)
|
||||
+ "-testString/>";
|
||||
|
||||
private static final String FOO_TEST_STRING = "<foo:" + ClassUtils.getShortName(StaxEventItemWriter.class)
|
||||
+ "-testString/>";
|
||||
|
||||
private SimpleMarshaller marshaller;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
resource = new FileSystemResource(File.createTempFile("StaxEventWriterOutputSourceTests", ".xml"));
|
||||
File directory = new File("target/data");
|
||||
directory.mkdirs();
|
||||
resource = new FileSystemResource(File.createTempFile("StaxEventWriterOutputSourceTests", ".xml", directory));
|
||||
writer = createItemWriter();
|
||||
executionContext = new ExecutionContext();
|
||||
}
|
||||
@@ -287,29 +297,68 @@ public class StaxEventItemWriterTests {
|
||||
public void testWriteRootTagWithNamespaceAndPrefix() throws Exception {
|
||||
writer.setRootTagName("{http://www.springframework.org/test}ns:root");
|
||||
writer.afterPropertiesSet();
|
||||
marshaller.setNamespace(writer.getRootTagNamespace());
|
||||
marshaller.setNamespacePrefix(writer.getRootTagNamespacePrefix());
|
||||
writer.open(executionContext);
|
||||
writer.write(items);
|
||||
writer.close();
|
||||
String content = getOutputFileContent();
|
||||
assertTrue("Wrong content: " + content, content
|
||||
.contains(("<ns:root xmlns:ns=\"http://www.springframework.org/test\">")));
|
||||
assertTrue("Wrong content: " + content, content.contains(TEST_STRING));
|
||||
assertTrue("Wrong content: " + content, content.contains(NS_TEST_STRING));
|
||||
assertTrue("Wrong content: " + content, content.contains(("</ns:root>")));
|
||||
assertTrue("Wrong content: " + content, content.contains(("<ns:root")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Item is written to the output file with additional namespaces and prefix.
|
||||
*/
|
||||
@Test
|
||||
public void testWriteRootTagWithAdditionalNamespace() throws Exception {
|
||||
writer.setRootTagName("{http://www.springframework.org/test}ns:root");
|
||||
marshaller.setNamespace("urn:org.test.foo");
|
||||
marshaller.setNamespacePrefix("foo");
|
||||
writer.setRootElementAttributes(Collections.singletonMap("xmlns:foo", "urn:org.test.foo"));
|
||||
writer.afterPropertiesSet();
|
||||
writer.open(executionContext);
|
||||
writer.write(items);
|
||||
writer.close();
|
||||
String content = getOutputFileContent();
|
||||
System.err.println(content);
|
||||
assertTrue("Wrong content: " + content, content
|
||||
.contains(("<ns:root xmlns:ns=\"http://www.springframework.org/test\" "
|
||||
+ "xmlns:foo=\"urn:org.test.foo\">")));
|
||||
assertTrue("Wrong content: " + content, content.contains(FOO_TEST_STRING));
|
||||
assertTrue("Wrong content: " + content, content.contains(("</ns:root>")));
|
||||
assertTrue("Wrong content: " + content, content.contains(("<ns:root")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes object's toString representation as XML comment.
|
||||
*/
|
||||
private static class SimpleMarshaller implements Marshaller {
|
||||
|
||||
private String namespacePrefix = "";
|
||||
|
||||
private String namespace = "";
|
||||
|
||||
public void setNamespace(String namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
public void setNamespacePrefix(String namespacePrefix) {
|
||||
this.namespacePrefix = namespacePrefix;
|
||||
}
|
||||
|
||||
public void marshal(Object graph, Result result) throws XmlMappingException, IOException {
|
||||
Assert.isInstanceOf(StaxResult.class, result);
|
||||
|
||||
StaxResult staxResult = (StaxResult) result;
|
||||
try {
|
||||
staxResult.getXMLEventWriter().add(
|
||||
XMLEventFactory.newInstance().createStartElement("", "", graph.toString()));
|
||||
XMLEventFactory.newInstance().createStartElement(namespacePrefix, namespace, graph.toString()));
|
||||
staxResult.getXMLEventWriter().add(
|
||||
XMLEventFactory.newInstance().createEndElement("", "", graph.toString()));
|
||||
XMLEventFactory.newInstance().createEndElement(namespacePrefix, namespace, graph.toString()));
|
||||
}
|
||||
catch (XMLStreamException e) {
|
||||
throw new RuntimeException("Exception while writing to output file", e);
|
||||
@@ -338,7 +387,7 @@ public class StaxEventItemWriterTests {
|
||||
StaxEventItemWriter<Object> source = new StaxEventItemWriter<Object>();
|
||||
source.setResource(resource);
|
||||
|
||||
Marshaller marshaller = new SimpleMarshaller();
|
||||
marshaller = new SimpleMarshaller();
|
||||
source.setMarshaller(marshaller);
|
||||
|
||||
source.setEncoding("UTF-8");
|
||||
@@ -351,5 +400,5 @@ public class StaxEventItemWriterTests {
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -546,7 +546,13 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.ws</groupId>
|
||||
<artifactId>spring-oxm</artifactId>
|
||||
<version>1.5.5</version>
|
||||
<version>1.5.8</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ws</groupId>
|
||||
<artifactId>spring-oxm-tiger</artifactId>
|
||||
<version>1.5.8</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
Reference in New Issue
Block a user