Author: davsclaus Date: Fri Oct 28 13:28:27 2011 New Revision: 1190303 URL: http://svn.apache.org/viewvc?rev=1190303&view=rev Log: CAMEL-4594: Fixed issue with using saxon for xpath splitting. Fixed issue with XPathFactory not thread safe. As well re-using default factory if possible.
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java camel/trunk/components/camel-saxon/src/test/java/org/apache/camel/builder/saxon/SaxonXPathSplitTest.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java?rev=1190303&r1=1190302&r2=1190303&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java Fri Oct 28 13:28:27 2011 @@ -44,7 +44,6 @@ import org.xml.sax.InputSource; import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Expression; -import org.apache.camel.Message; import org.apache.camel.Predicate; import org.apache.camel.RuntimeExpressionException; import org.apache.camel.Service; @@ -83,11 +82,12 @@ import static org.apache.camel.builder.x */ public class XPathBuilder implements Expression, Predicate, NamespaceAware, Service { private static final transient Logger LOG = LoggerFactory.getLogger(XPathBuilder.class); + private static XPathFactory defaultXPathFactory; + private final Queue<XPathExpression> pool = new ConcurrentLinkedQueue<XPathExpression>(); private final String text; private final ThreadLocal<MessageVariableResolver> variableResolver = new ThreadLocal<MessageVariableResolver>(); private final ThreadLocal<Exchange> exchange = new ThreadLocal<Exchange>(); - private XPathFactory xpathFactory; private Class<?> documentType = Document.class; // For some reason the default expression of "a/b" on a document such as @@ -373,32 +373,14 @@ public class XPathBuilder implements Exp // Properties // ------------------------------------------------------------------------- public XPathFactory getXPathFactory() throws XPathFactoryConfigurationException { - if (xpathFactory == null) { - if (objectModelUri != null) { - LOG.info("Using objectModelUri " + objectModelUri + " when creating XPathFactory"); - xpathFactory = XPathFactory.newInstance(objectModelUri); - return xpathFactory; - } - - // read system property and see if there is a factory set - Properties properties = System.getProperties(); - for (Map.Entry prop : properties.entrySet()) { - String key = (String) prop.getKey(); - if (key.startsWith(XPathFactory.DEFAULT_PROPERTY_NAME)) { - String uri = ObjectHelper.after(key, ":"); - if (uri != null) { - LOG.info("Using system property " + key + " with value: " + prop.getValue() + " when creating XPathFactory"); - xpathFactory = XPathFactory.newInstance(uri); - return xpathFactory; - } - } - } + if (xpathFactory != null) { + return xpathFactory; + } - LOG.debug("Creating default XPathFactory"); - xpathFactory = XPathFactory.newInstance(); + if (defaultXPathFactory == null) { + initDefaultXPathFactory(); } - - return xpathFactory; + return defaultXPathFactory; } public void setXPathFactory(XPathFactory xpathFactory) { @@ -699,7 +681,8 @@ public class XPathBuilder implements Exp return answer; } - protected XPathExpression createXPathExpression() throws XPathExpressionException, XPathFactoryConfigurationException { + protected synchronized XPathExpression createXPathExpression() throws XPathExpressionException, XPathFactoryConfigurationException { + // XPathFactory is not thread safe XPath xPath = getXPathFactory().newXPath(); xPath.setNamespaceContext(getNamespaceContext()); @@ -850,12 +833,42 @@ public class XPathBuilder implements Exp } public void start() throws Exception { + if (xpathFactory == null) { + initDefaultXPathFactory(); + } } public void stop() throws Exception { pool.clear(); } + protected synchronized void initDefaultXPathFactory() throws XPathFactoryConfigurationException { + if (defaultXPathFactory == null) { + if (objectModelUri != null) { + defaultXPathFactory = XPathFactory.newInstance(objectModelUri); + LOG.info("Using objectModelUri " + objectModelUri + " when created XPathFactory {}", defaultXPathFactory); + } + + if (defaultXPathFactory == null) { + // read system property and see if there is a factory set + Properties properties = System.getProperties(); + for (Map.Entry prop : properties.entrySet()) { + String key = (String) prop.getKey(); + if (key.startsWith(XPathFactory.DEFAULT_PROPERTY_NAME)) { + String uri = ObjectHelper.after(key, ":"); + if (uri != null) { + defaultXPathFactory = XPathFactory.newInstance(uri); + LOG.info("Using system property {} with value {} when created XPathFactory {}", new Object[]{key, uri, defaultXPathFactory}); + } + } + } + } + + defaultXPathFactory = XPathFactory.newInstance(); + LOG.info("Created default XPathFactory {}", defaultXPathFactory); + } + } + /** * On completion class which cleanup thread local resources */ Modified: camel/trunk/components/camel-saxon/src/test/java/org/apache/camel/builder/saxon/SaxonXPathSplitTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-saxon/src/test/java/org/apache/camel/builder/saxon/SaxonXPathSplitTest.java?rev=1190303&r1=1190302&r2=1190303&view=diff ============================================================================== --- camel/trunk/components/camel-saxon/src/test/java/org/apache/camel/builder/saxon/SaxonXPathSplitTest.java (original) +++ camel/trunk/components/camel-saxon/src/test/java/org/apache/camel/builder/saxon/SaxonXPathSplitTest.java Fri Oct 28 13:28:27 2011 @@ -18,7 +18,6 @@ package org.apache.camel.builder.saxon; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.test.junit4.CamelTestSupport; -import org.junit.Ignore; import org.junit.Test; /** @@ -27,7 +26,6 @@ import org.junit.Test; public class SaxonXPathSplitTest extends CamelTestSupport { @Test - @Ignore("This test fails") public void testSaxonXPathSplit() throws Exception { getMockEndpoint("mock:london").expectedMessageCount(1); getMockEndpoint("mock:paris").expectedMessageCount(1);