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/06/25 17:41:59 UTC

svn commit: r1353601 - in /camel/trunk/camel-core/src: main/java/org/apache/camel/language/bean/ main/java/org/apache/camel/model/language/ test/java/org/apache/camel/component/bean/

Author: davsclaus
Date: Mon Jun 25 15:41:57 2012
New Revision: 1353601

URL: http://svn.apache.org/viewvc?rev=1353601&view=rev
Log:
CAMEL-5392: Optimized bean expression to reuse bean holder to avoid re-introspecting the bean on subsequent evaluations. Thanks to Mark Hillary for the patch.

Added:
    camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanExpressionConcurrentTest.java
      - copied, changed from r1353590, camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanConcurrentTest.java
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/language/bean/BeanExpression.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/language/MethodCallExpression.java

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/language/bean/BeanExpression.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/bean/BeanExpression.java?rev=1353601&r1=1353600&r2=1353601&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/language/bean/BeanExpression.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/bean/BeanExpression.java Mon Jun 25 15:41:57 2012
@@ -19,6 +19,7 @@ package org.apache.camel.language.bean;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.ExchangePattern;
 import org.apache.camel.Expression;
@@ -37,28 +38,41 @@ import org.apache.camel.util.StringHelpe
 
 /**
  * Evaluates an expression using a bean method invocation
- *
- * @version 
  */
 public class BeanExpression implements Expression, Predicate {
-    private Object bean;
-    private String beanName;
-    private Class<?> type;
-    private String method;
+    private final Object bean;
+    private final String beanName;
+    private final Class<?> type;
+    private final String method;
+    private volatile BeanHolder beanHolder;
 
     public BeanExpression(Object bean, String method) {
         this.bean = bean;
         this.method = method;
+        this.beanName = null;
+        this.type = null;
     }
 
     public BeanExpression(String beanName, String method) {
         this.beanName = beanName;
         this.method = method;
+        this.bean = null;
+        this.type = null;
     }
 
     public BeanExpression(Class<?> type, String method) {
         this.type = type;
         this.method = method;
+        this.bean = null;
+        this.beanName = null;
+    }
+
+    public BeanExpression(BeanHolder beanHolder, String method) {
+        this.beanHolder = beanHolder;
+        this.method = method;
+        this.bean = null;
+        this.beanName = null;
+        this.type = null;
     }
 
     @Override
@@ -79,16 +93,10 @@ public class BeanExpression implements E
     }
 
     public Object evaluate(Exchange exchange) {
-        // either use registry lookup or a constant bean
-        BeanHolder holder;
-        if (bean != null) {
-            holder = new ConstantBeanHolder(bean, exchange.getContext());
-        } else if (beanName != null) {
-            holder = new RegistryBean(exchange.getContext(), beanName);
-        } else if (type != null) {
-            holder = new ConstantTypeBeanHolder(type, exchange.getContext());
-        } else {
-            throw new IllegalArgumentException("Either bean, beanName or type should be set on " + this);
+
+        // if the bean holder doesn't exist then create it using the context from the exchange
+        if (beanHolder == null) {
+            beanHolder = createBeanHolder(exchange.getContext());
         }
 
         // invoking the bean can either be the easy way or using OGNL
@@ -101,7 +109,7 @@ public class BeanExpression implements E
 
         if (OgnlHelper.isValidOgnlExpression(method)) {
             // okay the method is an ognl expression
-            OgnlInvokeProcessor ognl = new OgnlInvokeProcessor(holder, method);
+            OgnlInvokeProcessor ognl = new OgnlInvokeProcessor(beanHolder, method);
             try {
                 ognl.process(exchange);
                 return ognl.getResult();
@@ -110,7 +118,7 @@ public class BeanExpression implements E
             }
         } else {
             // regular non ognl invocation
-            InvokeProcessor invoke = new InvokeProcessor(holder, method);
+            InvokeProcessor invoke = new InvokeProcessor(beanHolder, method);
             try {
                 invoke.process(exchange);
                 return invoke.getResult();
@@ -131,6 +139,25 @@ public class BeanExpression implements E
     }
 
     /**
+     * Optimize to create the bean holder once, so we can reuse it for further
+     * evaluation, which is faster.
+     */
+    private synchronized BeanHolder createBeanHolder(CamelContext context) {
+        // either use registry lookup or a constant bean
+        BeanHolder holder;
+        if (bean != null) {
+            holder = new ConstantBeanHolder(bean, context);
+        } else if (beanName != null) {
+            holder = new RegistryBean(context, beanName);
+        } else if (type != null) {
+            holder = new ConstantTypeBeanHolder(type, context);
+        } else {
+            throw new IllegalArgumentException("Either bean, beanName or type should be set on " + this);
+        }
+        return holder;
+    }
+
+    /**
      * Invokes a given bean holder. The method name is optional.
      */
     private final class InvokeProcessor implements Processor {

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/language/MethodCallExpression.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/language/MethodCallExpression.java?rev=1353601&r1=1353600&r2=1353601&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/language/MethodCallExpression.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/language/MethodCallExpression.java Mon Jun 25 15:41:57 2012
@@ -28,6 +28,8 @@ import org.apache.camel.ExpressionIllega
 import org.apache.camel.Predicate;
 import org.apache.camel.component.bean.BeanHolder;
 import org.apache.camel.component.bean.BeanInfo;
+import org.apache.camel.component.bean.ConstantBeanHolder;
+import org.apache.camel.component.bean.ConstantTypeBeanHolder;
 import org.apache.camel.component.bean.MethodNotFoundException;
 import org.apache.camel.component.bean.RegistryBean;
 import org.apache.camel.language.bean.BeanExpression;
@@ -38,7 +40,7 @@ import org.apache.camel.util.OgnlHelper;
  * For expressions and predicates using the
  * <a href="http://camel.apache.org/bean-language.html">bean language</a>
  *
- * @version 
+ * @version
  */
 @XmlRootElement(name = "method")
 @XmlAccessorType(XmlAccessType.FIELD)
@@ -68,11 +70,11 @@ public class MethodCallExpression extend
         super(beanName);
         this.method = method;
     }
-    
+
     public MethodCallExpression(Object instance) {
         this(instance, null);
     }
-    
+
     public MethodCallExpression(Object instance, String method) {
         super(ObjectHelper.className(instance));
         // must use setter as they have special logic
@@ -83,7 +85,7 @@ public class MethodCallExpression extend
     public MethodCallExpression(Class<?> type) {
         this(type, null);
     }
-    
+
     public MethodCallExpression(Class<?> type, String method) {
         super(type.getName());
         this.beanType = type;
@@ -162,25 +164,30 @@ public class MethodCallExpression extend
             }
         }
 
+        BeanHolder holder;
         if (beanType != null) {
             // create a bean if there is a default public no-arg constructor
             if (ObjectHelper.hasDefaultPublicNoArgConstructor(beanType)) {
                 instance = camelContext.getInjector().newInstance(beanType);
-                answer = new BeanExpression(instance, getMethod());
+                holder = new ConstantBeanHolder(instance, camelContext);
             } else {
-                answer = new BeanExpression(beanType, getMethod());
+                holder = new ConstantTypeBeanHolder(beanType, camelContext);
             }
         } else if (instance != null) {
-            answer = new BeanExpression(instance, getMethod());
+            holder = new ConstantBeanHolder(instance, camelContext);
         } else {
             String ref = beanName();
             // if its a ref then check that the ref exists
-            BeanHolder holder = new RegistryBean(camelContext, ref);
+            BeanHolder regHolder = new RegistryBean(camelContext, ref);
             // get the bean which will check that it exists
-            instance = holder.getBean();
-            answer = new BeanExpression(instance, getMethod());
+            instance = regHolder.getBean();
+            holder = new ConstantBeanHolder(instance, camelContext);
         }
 
+        // create answer using the holder
+        answer = new BeanExpression(holder, getMethod());
+
+        // and do sanity check that if a method name was given, that it exists
         validateHasMethod(camelContext, instance, beanType, getMethod());
         return answer;
     }

Copied: camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanExpressionConcurrentTest.java (from r1353590, camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanConcurrentTest.java)
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanExpressionConcurrentTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanExpressionConcurrentTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanConcurrentTest.java&r1=1353590&r2=1353601&rev=1353601&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanConcurrentTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanExpressionConcurrentTest.java Mon Jun 25 15:41:57 2012
@@ -28,7 +28,7 @@ import org.apache.camel.impl.JndiRegistr
 /**
  * @version 
  */
-public class BeanConcurrentTest extends ContextTestSupport {
+public class BeanExpressionConcurrentTest extends ContextTestSupport {
 
     public void testBeanConcurrent() throws Exception {
         MockEndpoint mock = getMockEndpoint("mock:result");
@@ -75,7 +75,7 @@ public class BeanConcurrentTest extends 
             @Override
             public void configure() throws Exception {
                 from("seda:foo?concurrentConsumers=10").routeId("foo").noAutoStartup()
-                    .to("bean:myBean")
+                    .transform(method("myBean"))
                     .to("mock:result");
             }
         };