You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by dk...@apache.org on 2012/04/05 16:47:46 UTC

svn commit: r1309887 - in /camel/trunk/components/camel-jaxb/src: main/java/org/apache/camel/converter/jaxb/ test/java/org/apache/camel/converter/jaxb/ test/java/org/apache/camel/example/

Author: dkulp
Date: Thu Apr  5 14:47:46 2012
New Revision: 1309887

URL: http://svn.apache.org/viewvc?rev=1309887&view=rev
Log:
[CAMEL-3776] Change from pooling to using XMLStreamReaders for
everything which removes all the locks and much of the casting.
NOTE: right now, this REQUIRES woodstox as the StAX parser as the in-jdk
version is not thread safe in how StaxConverter uses it right now.

Modified:
    camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/FallbackTypeConverter.java
    camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java
    camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/converter/jaxb/JaxbDataFormatTest.java
    camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatConcurrentTest.java

Modified: camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/FallbackTypeConverter.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/FallbackTypeConverter.java?rev=1309887&r1=1309886&r2=1309887&view=diff
==============================================================================
--- camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/FallbackTypeConverter.java (original)
+++ camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/FallbackTypeConverter.java Thu Apr  5 14:47:46 2012
@@ -26,7 +26,6 @@ import java.io.UnsupportedEncodingExcept
 import java.io.Writer;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.concurrent.locks.ReentrantLock;
 
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
@@ -34,7 +33,6 @@ import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.stream.FactoryConfigurationError;
-import javax.xml.stream.XMLOutputFactory;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.XMLStreamWriter;
@@ -46,6 +44,7 @@ import org.apache.camel.Processor;
 import org.apache.camel.StreamCache;
 import org.apache.camel.TypeConverter;
 import org.apache.camel.component.bean.BeanInvocation;
+import org.apache.camel.converter.jaxp.StaxConverter;
 import org.apache.camel.spi.TypeConverterAware;
 import org.apache.camel.util.IOHelper;
 import org.slf4j.Logger;
@@ -57,13 +56,10 @@ import org.slf4j.LoggerFactory;
 public class FallbackTypeConverter implements TypeConverter, TypeConverterAware {
     private static final transient Logger LOG = LoggerFactory.getLogger(FallbackTypeConverter.class);
     private Map<Class<?>, JAXBContext> contexts = new HashMap<Class<?>, JAXBContext>();
-    private Map<Class<?>, Unmarshaller> unmarshallers = new HashMap<Class<?>, Unmarshaller>();
-    private XMLOutputFactory outputFactory;
     private TypeConverter parentTypeConverter;
+    private StaxConverter staxConverter = new StaxConverter();
     private boolean prettyPrint = true;
 
-    private ReentrantLock unmarshallerLock = new ReentrantLock();
-
     public boolean isPrettyPrint() {
         return prettyPrint;
     }
@@ -193,7 +189,7 @@ public class FallbackTypeConverter imple
                 marshaller.setProperty(Marshaller.JAXB_ENCODING, exchange.getProperty(Exchange.CHARSET_NAME, String.class));
             }
             if (needFiltering(exchange)) {
-                XMLStreamWriter writer = getOutputFactory().createXMLStreamWriter(buffer);
+                XMLStreamWriter writer = exchange.getContext().getTypeConverter().convertTo(XMLStreamWriter.class, buffer);
                 FilteringXmlStreamWriter filteringWriter = new FilteringXmlStreamWriter(writer);
                 marshaller.marshal(value, filteringWriter);
             } else {
@@ -206,16 +202,16 @@ public class FallbackTypeConverter imple
     }
 
     protected Object unmarshal(Unmarshaller unmarshaller, Exchange exchange, Object value) throws JAXBException, UnsupportedEncodingException, XMLStreamException {
-        unmarshallerLock.lock();
         try {
+            XMLStreamReader xmlReader = null;
             if (value instanceof XMLStreamReader) {
-                XMLStreamReader xmlReader = (XMLStreamReader) value;
-                return unmarshaller.unmarshal(xmlReader);
+                xmlReader = (XMLStreamReader) value;
             } else if (value instanceof InputStream) {
                 if (needFiltering(exchange)) {
-                    return unmarshaller.unmarshal(new NonXmlFilterReader(new InputStreamReader((InputStream)value, IOHelper.getCharsetName(exchange))));
+                    xmlReader = staxConverter.createXMLStreamReader(new NonXmlFilterReader(new InputStreamReader((InputStream)value, IOHelper.getCharsetName(exchange))));
+                } else {
+                    xmlReader = staxConverter.createXMLStreamReader((InputStream)value, exchange);
                 }
-                return unmarshaller.unmarshal((InputStream)value);
             } else if (value instanceof Reader) {
                 Reader reader = (Reader)value;
                 if (needFiltering(exchange)) {
@@ -223,17 +219,18 @@ public class FallbackTypeConverter imple
                         reader = new NonXmlFilterReader((Reader)value);
                     }
                 }
-                return unmarshaller.unmarshal(reader);
+                xmlReader = staxConverter.createXMLStreamReader(reader);
             } else if (value instanceof Source) {
-                return unmarshaller.unmarshal((Source)value);
+                xmlReader = staxConverter.createXMLStreamReader((Source)value);
+            } else {
+                throw new IllegalArgumentException("Cannot convert from " + value.getClass());
             }
+            return unmarshaller.unmarshal(xmlReader);
         } finally {
-            unmarshallerLock.unlock();
             if (value instanceof Closeable) {
                 IOHelper.close((Closeable)value, "Unmarshalling", LOG);
             }
         }
-        return null;
     }
 
     protected boolean needFiltering(Exchange exchange) {
@@ -251,19 +248,8 @@ public class FallbackTypeConverter imple
     }
 
     protected synchronized <T> Unmarshaller getOrCreateUnmarshaller(Class<T> type) throws JAXBException {
-        Unmarshaller unmarshaller = unmarshallers.get(type);
-        if (unmarshaller == null) {
-            JAXBContext context = createContext(type);
-            unmarshaller = context.createUnmarshaller();
-            unmarshallers.put(type, unmarshaller);
-        }
-        return unmarshaller;
+        JAXBContext context = createContext(type);
+        return context.createUnmarshaller();
     }
 
-    public XMLOutputFactory getOutputFactory() {
-        if (outputFactory == null) {
-            outputFactory = XMLOutputFactory.newInstance();
-        }
-        return outputFactory;
-    }
 }

Modified: camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java?rev=1309887&r1=1309886&r2=1309887&view=diff
==============================================================================
--- camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java (original)
+++ camel/trunk/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java Thu Apr  5 14:47:46 2012
@@ -21,7 +21,6 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
-import java.util.concurrent.locks.ReentrantLock;
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBElement;
 import javax.xml.bind.JAXBException;
@@ -29,12 +28,9 @@ import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
 import javax.xml.namespace.QName;
 import javax.xml.stream.FactoryConfigurationError;
-import javax.xml.stream.XMLOutputFactory;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.XMLStreamWriter;
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
@@ -70,8 +66,6 @@ public class JaxbDataFormat extends Serv
     private Class<Object> partialClass;
 
     private TypeConverter typeConverter;
-    private Unmarshaller unmarshaller;
-    private ReentrantLock lock = new ReentrantLock();
 
     public JaxbDataFormat() {
     }
@@ -129,7 +123,7 @@ public class JaxbDataFormat extends Serv
 
     private FilteringXmlStreamWriter createFilteringWriter(OutputStream stream)
         throws XMLStreamException, FactoryConfigurationError {
-        XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(stream);
+        XMLStreamWriter writer = typeConverter.convertTo(XMLStreamWriter.class, stream);
         FilteringXmlStreamWriter filteringWriter = new FilteringXmlStreamWriter(writer);
         return filteringWriter;
     }
@@ -138,29 +132,17 @@ public class JaxbDataFormat extends Serv
         try {
             Object answer;
 
-            lock.lock();
-            try {
-                if (partialClass != null) {
-                    // partial unmarshalling
-                    if (needFiltering(exchange)) {
-                        Source source = new StreamSource(createNonXmlFilterReader(exchange, stream));
-                        answer = getUnmarshaller().unmarshal(source, partialClass);
-                    } else {
-                        XMLStreamReader xmlReader = typeConverter.convertTo(XMLStreamReader.class, stream);
-                        answer = getUnmarshaller().unmarshal(xmlReader, partialClass);
-                    }
-
-                } else {
-                    if (needFiltering(exchange)) {
-                        NonXmlFilterReader reader = createNonXmlFilterReader(exchange, stream);
-                        answer = getUnmarshaller().unmarshal(reader);
-                    } else  {
-                        XMLStreamReader xmlReader = typeConverter.convertTo(XMLStreamReader.class, stream);
-                        answer = getUnmarshaller().unmarshal(xmlReader);
-                    }
-                }
-            }  finally {
-                lock.unlock();
+            XMLStreamReader xmlReader;
+            if (needFiltering(exchange)) {
+                xmlReader = typeConverter.convertTo(XMLStreamReader.class, createNonXmlFilterReader(exchange, stream));
+            } else {
+                xmlReader = typeConverter.convertTo(XMLStreamReader.class, stream);
+            }
+            if (partialClass != null) {
+                // partial unmarshalling
+                answer = createUnmarshaller().unmarshal(xmlReader, partialClass);
+            } else {
+                answer = createUnmarshaller().unmarshal(xmlReader);
             }
 
             if (answer instanceof JAXBElement && isIgnoreJAXBElement()) {
@@ -263,10 +245,6 @@ public class JaxbDataFormat extends Serv
         this.camelContext = camelContext;
     }
 
-    public Unmarshaller getUnmarshaller() {
-        return unmarshaller;
-    }
-
     @Override
     protected void doStart() throws Exception {
         ObjectHelper.notNull(camelContext, "CamelContext");
@@ -278,7 +256,6 @@ public class JaxbDataFormat extends Serv
         if (partClass != null) {
             partialClass = camelContext.getClassResolver().resolveMandatoryClass(partClass, Object.class);
         }
-        unmarshaller = getContext().createUnmarshaller();
         typeConverter = camelContext.getTypeConverter();
     }
 
@@ -306,5 +283,9 @@ public class JaxbDataFormat extends Serv
             return JAXBContext.newInstance();
         }
     }
+    
+    protected Unmarshaller createUnmarshaller() throws JAXBException {
+        return getContext().createUnmarshaller();
+    }
 
 }

Modified: camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/converter/jaxb/JaxbDataFormatTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/converter/jaxb/JaxbDataFormatTest.java?rev=1309887&r1=1309886&r2=1309887&view=diff
==============================================================================
--- camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/converter/jaxb/JaxbDataFormatTest.java (original)
+++ camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/converter/jaxb/JaxbDataFormatTest.java Thu Apr  5 14:47:46 2012
@@ -19,10 +19,8 @@ package org.apache.camel.converter.jaxb;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
 
-import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
@@ -35,18 +33,11 @@ import org.apache.camel.impl.DefaultCame
 import org.apache.camel.impl.DefaultExchange;
 import org.junit.Before;
 import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
 
 
 import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.hamcrest.CoreMatchers.not;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.argThat;
 import static org.mockito.Matchers.isA;
 import static org.mockito.Matchers.same;
@@ -133,8 +124,9 @@ public class JaxbDataFormatTest {
         jaxbDataFormat.setFilterNonXmlChars(false);
 
         jaxbDataFormatMock = spy(jaxbDataFormat);
+
         unmarshallerMock = mock(Unmarshaller.class);
-        doReturn(unmarshallerMock).when(jaxbDataFormatMock).getUnmarshaller();
+        doReturn(unmarshallerMock).when(jaxbDataFormatMock).createUnmarshaller();
 
         jaxbDataFormatMock.unmarshal(new DefaultExchange(camelContext), new ByteArrayInputStream(new byte[] {}));
 
@@ -144,14 +136,14 @@ public class JaxbDataFormatTest {
     @Test
     public void testUnmarshalFilteringEnabled() throws IOException, JAXBException {
         jaxbDataFormat.setFilterNonXmlChars(true);
-
         jaxbDataFormatMock = spy(jaxbDataFormat);
+        
         unmarshallerMock = mock(Unmarshaller.class);
-        doReturn(unmarshallerMock).when(jaxbDataFormatMock).getUnmarshaller();
+        doReturn(unmarshallerMock).when(jaxbDataFormatMock).createUnmarshaller();
 
         jaxbDataFormatMock.unmarshal(new DefaultExchange(camelContext), new ByteArrayInputStream(new byte[] {}));
 
-        verify(unmarshallerMock).unmarshal(any(NonXmlFilterReader.class));
+        verify(unmarshallerMock).unmarshal((XMLStreamReader) argThat(instanceOf(XMLStreamReader.class)));
     }
 
 }

Modified: camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatConcurrentTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatConcurrentTest.java?rev=1309887&r1=1309886&r2=1309887&view=diff
==============================================================================
--- camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatConcurrentTest.java (original)
+++ camel/trunk/components/camel-jaxb/src/test/java/org/apache/camel/example/DataFormatConcurrentTest.java Thu Apr  5 14:47:46 2012
@@ -16,11 +16,15 @@
  */
 package org.apache.camel.example;
 
+import java.io.StringWriter;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.converter.jaxb.JaxbDataFormat;
@@ -34,11 +38,29 @@ import org.junit.Test;
 public class DataFormatConcurrentTest extends CamelTestSupport {
 
     private int size = 2000;
+    
+    private int fooBarSize = 50;
+    
+    public String createPayload() throws Exception {
+        Foo foo = new Foo();
+        for (int x = 0; x < fooBarSize; x++) {
+            Bar bar = new Bar();
+            bar.setName("Name: " + x);
+            bar.setValue("value: " + x);
+            foo.getBarRefs().add(bar);
+        }
+        Marshaller m = JAXBContext.newInstance(Foo.class, Bar.class).createMarshaller();
+        StringWriter writer = new StringWriter();
+        m.marshal(foo, writer);
+        return writer.toString();
+    }
 
     @Test
     public void testUnmarshallConcurrent() throws Exception {
         int counter = 10000;
-        final String payload = "<purchaseOrder name='Wine' amount='123.45' price='2.22'/>";
+        //final String payload = "<purchaseOrder name='Wine' amount='123.45' price='2.22'/>";
+        final String payload = createPayload();
+        //System.out.println("Length: " + payload.length());
         final CountDownLatch latch = new CountDownLatch(counter);
         template.setDefaultEndpointUri("direct:unmarshal");
 
@@ -54,7 +76,7 @@ public class DataFormatConcurrentTest ex
         }
 
         // should finish on fast machines in less than 3 seconds
-        assertTrue(latch.await(10, TimeUnit.SECONDS));
+        assertTrue(latch.await(15, TimeUnit.SECONDS));
         //long end = System.currentTimeMillis();
         //System.out.println("took " + (end - start) + "ms");
     }