Author: davsclaus Date: Fri Feb 27 09:12:21 2009 New Revision: 748450 URL: http://svn.apache.org/viewvc?rev=748450&view=rev Log: Merged revisions 748436 via svnmerge from https://svn.apache.org/repos/asf/camel/trunk
........ r748436 | davsclaus | 2009-02-27 09:53:05 +0100 (Fri, 27 Feb 2009) | 1 line CAMEL-1401: Fixed thread safe issue with JAXBDataFormat. ........ Added: camel/branches/camel-1.x/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatConcurrentTest.java - copied, changed from r748436, camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatConcurrentTest.java camel/branches/camel-1.x/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatDataSetTest.java - copied unchanged from r748436, camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatDataSetTest.java Modified: camel/branches/camel-1.x/ (props changed) camel/branches/camel-1.x/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/FallbackTypeConverter.java camel/branches/camel-1.x/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbConverter.java camel/branches/camel-1.x/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java camel/branches/camel-1.x/components/camel-jaxb/src/test/java/org/apache/camel/example/JAXBConvertTest.java Propchange: camel/branches/camel-1.x/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Fri Feb 27 09:12:21 2009 @@ -1 +1 @@ -/camel/trunk:736980,739733,739904,740251,740295,740306,740596,740663,741848,742231,742705,742739,742854,742856,742898,742906,743613,743762,743773,743920,743959-743960,744123,745105,745367,745541,745751,745826,745978,746269,746872,746895,746962,747258,747678-747704,748392 +/camel/trunk:736980,739733,739904,740251,740295,740306,740596,740663,741848,742231,742705,742739,742854,742856,742898,742906,743613,743762,743773,743920,743959-743960,744123,745105,745367,745541,745751,745826,745978,746269,746872,746895,746962,747258,747678-747704,748392,748436 Propchange: camel/branches/camel-1.x/ ------------------------------------------------------------------------------ Binary property 'svnmerge-integrated' - no diff available. Modified: camel/branches/camel-1.x/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/FallbackTypeConverter.java URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/FallbackTypeConverter.java?rev=748450&r1=748449&r2=748450&view=diff ============================================================================== --- camel/branches/camel-1.x/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/FallbackTypeConverter.java (original) +++ camel/branches/camel-1.x/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/FallbackTypeConverter.java Fri Feb 27 09:12:21 2009 @@ -21,6 +21,8 @@ import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; @@ -44,6 +46,7 @@ */ public class FallbackTypeConverter implements TypeConverter, TypeConverterAware { private static final transient Log LOG = LogFactory.getLog(FallbackTypeConverter.class); + private Map<Class, JAXBContext> contexts = new HashMap<Class, JAXBContext>(); private TypeConverter parentTypeConverter; private boolean prettyPrint = true; @@ -85,15 +88,19 @@ protected <T> boolean isJaxbType(Class<T> type) { XmlRootElement element = type.getAnnotation(XmlRootElement.class); - boolean jaxbType = element != null; - return jaxbType; + return element != null; } /** * Lets try parse via JAXB */ protected <T> T unmarshall(Class<T> type, Object value) throws JAXBException { + if (value == null) { + throw new IllegalArgumentException("Cannot convert from null value to JAXBSource"); + } + JAXBContext context = createContext(type); + // must create a new instance of unmarshaller as its not thred safe Unmarshaller unmarshaller = context.createUnmarshaller(); if (parentTypeConverter != null) { @@ -136,6 +143,7 @@ } catch (NoTypeConversionAvailableException e) { // lets try a stream StringWriter buffer = new StringWriter(); + // must create a new instance of marshaller as its not thred safe Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, isPrettyPrint() ? Boolean.TRUE : Boolean.FALSE); marshaller.marshal(value, buffer); @@ -172,8 +180,13 @@ return null; } - protected <T> JAXBContext createContext(Class<T> type) throws JAXBException { - JAXBContext context = JAXBContext.newInstance(type); + protected synchronized <T> JAXBContext createContext(Class<T> type) throws JAXBException { + JAXBContext context = contexts.get(type); + if (context == null) { + context = JAXBContext.newInstance(type); + contexts.put(type, context); + } return context; } + } Modified: camel/branches/camel-1.x/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbConverter.java URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbConverter.java?rev=748450&r1=748449&r2=748450&view=diff ============================================================================== --- camel/branches/camel-1.x/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbConverter.java (original) +++ camel/branches/camel-1.x/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbConverter.java Fri Feb 27 09:12:21 2009 @@ -37,32 +37,28 @@ * @version $Revision$ */ public final class JaxbConverter { - private XmlConverter jaxbConverter; + private XmlConverter xmlConverter = new XmlConverter(); private Map<Class, JAXBContext> contexts = new HashMap<Class, JAXBContext>(); - public XmlConverter getJaxbConverter() { - if (jaxbConverter == null) { - jaxbConverter = new XmlConverter(); - } - return jaxbConverter; - } - - public void setJaxbConverter(XmlConverter jaxbConverter) { - this.jaxbConverter = jaxbConverter; - } - @Converter public JAXBSource toSource(@HasAnnotation(XmlRootElement.class)Object value) throws JAXBException { + if (value == null) { + throw new IllegalArgumentException("Cannot convert from null value to JAXBSource"); + } JAXBContext context = getJaxbContext(value); return new JAXBSource(context, value); } @Converter public Document toDocument(@HasAnnotation(XmlRootElement.class)Object value) throws JAXBException, ParserConfigurationException { + if (value == null) { + throw new IllegalArgumentException("Cannot convert from null value to JAXBSource"); + } JAXBContext context = getJaxbContext(value); + // must create a new instance of marshaller as its not thred safe Marshaller marshaller = context.createMarshaller(); - Document doc = getJaxbConverter().createDocument(); + Document doc = xmlConverter.createDocument(); marshaller.marshal(value, doc); return doc; } @@ -80,19 +76,13 @@ } private synchronized JAXBContext getJaxbContext(Object value) throws JAXBException { - JAXBContext context = contexts.get(value.getClass()); + Class type = value.getClass(); + JAXBContext context = contexts.get(type); if (context == null) { - context = createJaxbContext(value); - contexts.put(value.getClass(), context); + context = JAXBContext.newInstance(type); + contexts.put(type, context); } return context; } - private JAXBContext createJaxbContext(Object value) throws JAXBException { - if (value == null) { - throw new IllegalArgumentException("Cannot convert from null value to JAXBSource"); - } - return JAXBContext.newInstance(value.getClass()); - } - } Modified: camel/branches/camel-1.x/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java?rev=748450&r1=748449&r2=748450&view=diff ============================================================================== --- camel/branches/camel-1.x/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java (original) +++ camel/branches/camel-1.x/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java Fri Feb 27 09:12:21 2009 @@ -19,12 +19,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; - import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; -import javax.xml.bind.Unmarshaller; import org.apache.camel.Exchange; import org.apache.camel.spi.DataFormat; @@ -41,8 +38,6 @@ private String contextPath; private boolean prettyPrint = true; private boolean ignoreJAXBElement = true; - private Marshaller marshaller; - private Unmarshaller unmarshaller; public JaxbDataFormat() { } @@ -57,7 +52,8 @@ public void marshal(Exchange exchange, Object graph, OutputStream stream) throws IOException { try { - getMarshaller().marshal(graph, stream); + // must create a new instance of marshaller as its not thred safe + getContext().createMarshaller().marshal(graph, stream); } catch (JAXBException e) { throw IOHelper.createIOException(e); } @@ -65,7 +61,8 @@ public Object unmarshal(Exchange exchange, InputStream stream) throws IOException, ClassNotFoundException { try { - Object answer = getUnmarshaller().unmarshal(stream); + // must create a new instance of unmarshaller as its not thred safe + Object answer = getContext().createUnmarshaller().unmarshal(stream); if (answer instanceof JAXBElement && isIgnoreJAXBElement()) { answer = ((JAXBElement)answer).getValue(); } @@ -85,7 +82,7 @@ ignoreJAXBElement = flag; } - public JAXBContext getContext() throws JAXBException { + public synchronized JAXBContext getContext() throws JAXBException { if (context == null) { context = createContext(); } @@ -104,17 +101,6 @@ this.contextPath = contextPath; } - public Marshaller getMarshaller() throws JAXBException { - if (marshaller == null) { - marshaller = getContext().createMarshaller(); - } - return marshaller; - } - - public void setMarshaller(Marshaller marshaller) { - this.marshaller = marshaller; - } - public boolean isPrettyPrint() { return prettyPrint; } @@ -123,17 +109,6 @@ this.prettyPrint = prettyPrint; } - public Unmarshaller getUnmarshaller() throws JAXBException { - if (unmarshaller == null) { - unmarshaller = getContext().createUnmarshaller(); - } - return unmarshaller; - } - - public void setUnmarshaller(Unmarshaller unmarshaller) { - this.unmarshaller = unmarshaller; - } - protected JAXBContext createContext() throws JAXBException { if (contextPath != null) { return JAXBContext.newInstance(contextPath); Copied: camel/branches/camel-1.x/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatConcurrentTest.java (from r748436, camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatConcurrentTest.java) URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatConcurrentTest.java?p2=camel/branches/camel-1.x/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatConcurrentTest.java&p1=camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatConcurrentTest.java&r1=748436&r2=748450&rev=748450&view=diff ============================================================================== --- camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatConcurrentTest.java (original) +++ camel/branches/camel-1.x/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatConcurrentTest.java Fri Feb 27 09:12:21 2009 @@ -56,7 +56,7 @@ bean.setAmount(23); bean.setPrice(2.5); - template.sendBody("seda:start?size=" + size + "&concurrentConsumers=5", bean); + template.sendBody("seda:start?size=" + size, bean); } }); } @@ -70,7 +70,7 @@ DataFormat jaxb = new JaxbDataFormat("org.apache.camel.example"); // use seda that supports concurrent consumers for concurrency - from("seda:start?size=" + size + "&concurrentConsumers=5").marshal(jaxb).convertBodyTo(String.class).to("mock:result"); + from("seda:start?size=" + size).thread(5).marshal(jaxb).convertBodyTo(String.class).to("mock:result"); } }; } Modified: camel/branches/camel-1.x/components/camel-jaxb/src/test/java/org/apache/camel/example/JAXBConvertTest.java URL: http://svn.apache.org/viewvc/camel/branches/camel-1.x/components/camel-jaxb/src/test/java/org/apache/camel/example/JAXBConvertTest.java?rev=748450&r1=748449&r2=748450&view=diff ============================================================================== --- camel/branches/camel-1.x/components/camel-jaxb/src/test/java/org/apache/camel/example/JAXBConvertTest.java (original) +++ camel/branches/camel-1.x/components/camel-jaxb/src/test/java/org/apache/camel/example/JAXBConvertTest.java Fri Feb 27 09:12:21 2009 @@ -41,6 +41,25 @@ assertNotNull("Purchase order should not be null!", purchaseOrder); assertEquals("name", "foo", purchaseOrder.getName()); assertEquals("amount", 123.45, purchaseOrder.getAmount()); + assertEquals("price", 2.22, purchaseOrder.getPrice()); + } + + public void testConverterTwice() throws Exception { + PurchaseOrder purchaseOrder = converter.convertTo(PurchaseOrder.class, + "<purchaseOrder name='foo' amount='123.45' price='2.22'/>"); + + assertNotNull("Purchase order should not be null!", purchaseOrder); + assertEquals("name", "foo", purchaseOrder.getName()); + assertEquals("amount", 123.45, purchaseOrder.getAmount()); + assertEquals("price", 2.22, purchaseOrder.getPrice()); + + PurchaseOrder purchaseOrder2 = converter.convertTo(PurchaseOrder.class, + "<purchaseOrder name='bar' amount='5.12' price='3.33'/>"); + + assertNotNull("Purchase order should not be null!", purchaseOrder2); + assertEquals("name", "bar", purchaseOrder2.getName()); + assertEquals("amount", 5.12, purchaseOrder2.getAmount()); + assertEquals("amount", 3.33, purchaseOrder2.getPrice()); } public void testStreamShouldBeClosed() throws Exception {