You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2012/08/13 18:06:44 UTC
svn commit: r1372485 - in /camel/trunk/camel-core/src:
main/java/org/apache/camel/builder/xml/XPathBuilder.java
test/java/org/apache/camel/processor/BeanOgnMethodWithXPathInjectionTest.java
Author: davsclaus
Date: Mon Aug 13 16:06:44 2012
New Revision: 1372485
URL: http://svn.apache.org/viewvc?rev=1372485&view=rev
Log:
CAMEL-5501: Optimized XPathBuilder to cleanup thread locals after evaluation. Optimized performance under load by only using 1 thread local. Ensures better GC as well when using @XPath annotation.
Added:
camel/trunk/camel-core/src/test/java/org/apache/camel/processor/BeanOgnMethodWithXPathInjectionTest.java
- copied, changed from r1372409, camel/trunk/camel-core/src/test/java/org/apache/camel/processor/BeanWithXPathInjectionTest.java
Modified:
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.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=1372485&r1=1372484&r2=1372485&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 Mon Aug 13 16:06:44 2012
@@ -92,8 +92,8 @@ public class XPathBuilder implements Exp
private final Queue<XPathExpression> pool = new ConcurrentLinkedQueue<XPathExpression>();
private final Queue<XPathExpression> poolLogNamespaces = new ConcurrentLinkedQueue<XPathExpression>();
private final String text;
- private final ThreadLocal<MessageVariableResolver> variableResolver = new ThreadLocal<MessageVariableResolver>();
private final ThreadLocal<Exchange> exchange = new ThreadLocal<Exchange>();
+ private final MessageVariableResolver variableResolver = new MessageVariableResolver(exchange);
private XPathFactory xpathFactory;
private Class<?> documentType = Document.class;
// For some reason the default expression of "a/b" on a document such as
@@ -133,19 +133,23 @@ public class XPathBuilder implements Exp
}
public boolean matches(Exchange exchange) {
- // add on completion so the thread locals is removed when exchange is done
- exchange.addOnCompletion(new XPathBuilderOnCompletion());
-
- Object booleanResult = evaluateAs(exchange, XPathConstants.BOOLEAN);
- return exchange.getContext().getTypeConverter().convertTo(Boolean.class, booleanResult);
+ try {
+ Object booleanResult = evaluateAs(exchange, XPathConstants.BOOLEAN);
+ return exchange.getContext().getTypeConverter().convertTo(Boolean.class, booleanResult);
+ } finally {
+ // remove the thread local after usage
+ this.exchange.remove();
+ }
}
public <T> T evaluate(Exchange exchange, Class<T> type) {
- // add on completion so the thread locals is removed when exchange is done
- exchange.addOnCompletion(new XPathBuilderOnCompletion());
-
- Object result = evaluate(exchange);
- return exchange.getContext().getTypeConverter().convertTo(type, result);
+ try {
+ Object result = evaluate(exchange);
+ return exchange.getContext().getTypeConverter().convertTo(type, result);
+ } finally {
+ // remove the thread local after usage
+ this.exchange.remove();
+ }
}
/**
@@ -165,8 +169,7 @@ public class XPathBuilder implements Exp
try {
return matches(dummy);
} finally {
- // remove the dummy from the thread local after usage
- variableResolver.remove();
+ // remove the thread local after usage
exchange.remove();
}
}
@@ -189,8 +192,7 @@ public class XPathBuilder implements Exp
try {
return evaluate(dummy, type);
} finally {
- // remove the dummy from the thread local after usage
- variableResolver.remove();
+ // remove the thread local after usage
exchange.remove();
}
}
@@ -213,9 +215,8 @@ public class XPathBuilder implements Exp
try {
return evaluate(dummy, String.class);
} finally {
- // remove the dummy from the thread local after usage
- variableResolver.remove();
- exchange.remove();
+ // remove the thread local after usage
+ this.exchange.remove();
}
}
@@ -1006,12 +1007,7 @@ public class XPathBuilder implements Exp
}
private MessageVariableResolver getVariableResolver() {
- MessageVariableResolver resolver = variableResolver.get();
- if (resolver == null) {
- resolver = new MessageVariableResolver(exchange);
- variableResolver.set(resolver);
- }
- return resolver;
+ return variableResolver;
}
public void start() throws Exception {
@@ -1052,33 +1048,4 @@ public class XPathBuilder implements Exp
}
}
- /**
- * On completion class which cleanup thread local resources
- */
- private final class XPathBuilderOnCompletion extends SynchronizationAdapter {
-
- @Override
- public void onDone(Exchange exchange) {
- // when the exchange is done, then cleanup thread locals if they are still
- // pointing to this exchange that was done
- if (exchange.equals(XPathBuilder.this.exchange.get())) {
- // cleanup thread locals after usage
- XPathBuilder.this.variableResolver.remove();
- XPathBuilder.this.exchange.remove();
- }
- }
-
- @Override
- public boolean allowHandover() {
- // this completion should not be handed over, as we want to execute it
- // on current thread as the thread locals is bound the current thread
- return false;
- }
-
- @Override
- public String toString() {
- return "XPathBuilderOnCompletion";
- }
- }
-
}
Copied: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/BeanOgnMethodWithXPathInjectionTest.java (from r1372409, camel/trunk/camel-core/src/test/java/org/apache/camel/processor/BeanWithXPathInjectionTest.java)
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/BeanOgnMethodWithXPathInjectionTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/processor/BeanOgnMethodWithXPathInjectionTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/processor/BeanWithXPathInjectionTest.java&r1=1372409&r2=1372485&rev=1372485&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/BeanWithXPathInjectionTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/BeanOgnMethodWithXPathInjectionTest.java Mon Aug 13 16:06:44 2012
@@ -28,15 +28,17 @@ import org.slf4j.LoggerFactory;
/**
* @version
*/
-public class BeanWithXPathInjectionTest extends ContextTestSupport {
+public class BeanOgnMethodWithXPathInjectionTest extends ContextTestSupport {
private static final transient Logger LOG = LoggerFactory.getLogger(BeanRouteTest.class);
protected MyBean myBean = new MyBean();
+ protected MyOtherBean myOtherBean = new MyOtherBean(myBean);
public void testSendMessage() throws Exception {
String expectedBody = "<env:Envelope xmlns:env='http://www.w3.org/2003/05/soap-envelope'><env:Body>"
+ "<foo>bar</foo></env:Body></env:Envelope>";
- template.sendBodyAndHeader("direct:in", expectedBody, "foo", "bar");
+ Object out = template.requestBodyAndHeader("direct:in", expectedBody, "foo", "bar");
+ assertEquals("bar", out);
assertEquals("bean body: " + myBean, expectedBody, myBean.body);
assertEquals("bean foo: " + myBean, "bar", myBean.foo);
@@ -47,7 +49,8 @@ public class BeanWithXPathInjectionTest
String expectedBody = "<env:Envelope xmlns:env='http://www.w3.org/2003/05/soap-envelope'><env:Body>"
+ "<foo>bar</foo></env:Body></env:Envelope>";
- template.sendBodyAndHeader("direct:in", expectedBody, "foo", "bar");
+ Object out = template.requestBodyAndHeader("direct:in", expectedBody, "foo", "bar");
+ assertEquals("bar", out);
assertEquals("bean body: " + myBean, expectedBody, myBean.body);
assertEquals("bean foo: " + myBean, "bar", myBean.foo);
@@ -56,7 +59,8 @@ public class BeanWithXPathInjectionTest
String expectedBody2 = "<env:Envelope xmlns:env='http://www.w3.org/2003/05/soap-envelope'><env:Body>"
+ "<foo>baz</foo></env:Body></env:Envelope>";
- template.sendBodyAndHeader("direct:in", expectedBody2, "foo", "baz");
+ Object out2 = template.requestBodyAndHeader("direct:in", expectedBody2, "foo", "bar");
+ assertEquals("baz", out2);
assertEquals("bean body: " + myBean, expectedBody2, myBean.body);
assertEquals("bean foo: " + myBean, "baz", myBean.foo);
@@ -66,17 +70,33 @@ public class BeanWithXPathInjectionTest
protected Context createJndiContext() throws Exception {
JndiContext answer = new JndiContext();
answer.bind("myBean", myBean);
+ answer.bind("myOtherBean", myOtherBean);
return answer;
}
protected RouteBuilder createRouteBuilder() {
return new RouteBuilder() {
public void configure() {
- from("direct:in").beanRef("myBean");
+ from("direct:in")
+ .transform().method("myOtherBean", "doSomething.read");
}
};
}
+ public static class MyOtherBean {
+
+ private final MyBean inner;
+
+ public MyOtherBean(MyBean inner) {
+ this.inner = inner;
+ }
+
+ public MyBean doSomething() {
+ return inner;
+ }
+
+ }
+
public static class MyBean {
public String body;
public String foo;
@@ -86,10 +106,11 @@ public class BeanWithXPathInjectionTest
return "MyBean[foo: " + foo + " body: " + body + "]";
}
- public void read(String body, @XPath("/soap:Envelope/soap:Body/foo/text()") String foo) {
+ public String read(String body, @XPath("/soap:Envelope/soap:Body/foo/text()") String foo) {
this.foo = foo;
this.body = body;
LOG.info("read() method called on " + this);
+ return foo;
}
}
}