You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by js...@apache.org on 2008/08/11 18:31:44 UTC

svn commit: r684800 - in /activemq/camel/trunk/camel-core/src: main/java/org/apache/camel/ main/java/org/apache/camel/component/bean/ test/java/org/apache/camel/component/bean/

Author: jstrachan
Date: Mon Aug 11 09:31:43 2008
New Revision: 684800

URL: http://svn.apache.org/viewvc?rev=684800&view=rev
Log:
added a test case for CAMEL-810 showing the use of class, base class, interface and method level annotations all working together nicely

Added:
    activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java   (contents, props changed)
      - copied, changed from r684774, activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanInfoTestTest.java
Modified:
    activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/OneWay.java
    activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java
    activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java

Modified: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/OneWay.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/OneWay.java?rev=684800&r1=684799&r2=684800&view=diff
==============================================================================
--- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/OneWay.java (original)
+++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/OneWay.java Mon Aug 11 09:31:43 2008
@@ -25,6 +25,22 @@
  * Marks a method as being a one way asynchronous invocation so that if you are using some kind of
  * <a href="http://activemq.apache.org/camel/spring-remoting.html">Spring Remoting</a> then the method invocation will be asynchronous.
  *
+ * You can then either annotate specific methods as being oneway / asynchronous via
+ * <code>
+ * @OneWay
+ * public void myMethod() {...}
+ * </code>
+ *
+ * or you can say that all methods are by default asynchronous on an interface by annotating the interface
+ * 
+ * <code>
+ * @OneWay
+ * public interface Foo {
+ *   void methodOne();
+ *   void methodTwo();
+ * }
+ * </code>
+ *
  * If you wish to use some other {@link ExchangePattern} than {@link org.apache.camel.ExchangePattern#InOnly} you could use something like
  *
  * <code>
@@ -39,13 +55,27 @@
  * public void myMethod() {...}
  * </code>
  *
+ * You can also use the annotation to disable the one way pattern on specific methods as follows...
+ *
+ * <code>
+ * @OneWay
+ * public interface Foo {
+ *   void methodOne();
+ *
+ *   @OneWay(ExchangePattern.InOut)
+ *   void notOneWayMethod();
+ * }
+ *
+ * Where the <b>notOneWayMethod</b> will not be using one way invocation while all other methods will inherit the InOut exchange pattern
+ *
+ * </code>
  * @see ExchangePattern
  * @see Exchange#getPattern()
  *
  * @version $Revision$
  */
 @Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD })
+@Target({ElementType.TYPE, ElementType.METHOD})
 public @interface OneWay {
 
     /**

Modified: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java?rev=684800&r1=684799&r2=684800&view=diff
==============================================================================
--- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java (original)
+++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java Mon Aug 11 09:31:43 2008
@@ -58,6 +58,7 @@
     private List<MethodInfo> operationsWithBody = new ArrayList<MethodInfo>();
     private List<MethodInfo> operationsWithCustomAnnotation = new ArrayList<MethodInfo>();
     private Map<Method, MethodInfo> methodMap = new HashMap<Method, MethodInfo>();
+    private BeanInfo superBeanInfo;
 
     public BeanInfo(CamelContext camelContext, Class type) {
         this(camelContext, type, createParameterMappingStrategy(camelContext));
@@ -150,7 +151,18 @@
      * @param method
      */
     public MethodInfo getMethodInfo(Method method) {
-        return methodMap.get(method);
+        MethodInfo answer = methodMap.get(method);
+        if (answer == null) {
+            // maybe the method is defined on a base class?
+            if (superBeanInfo == null && type != Object.class) {
+                Class superclass = type.getSuperclass();
+                if (superclass != null && superclass != Object.class) {
+                    superBeanInfo = new BeanInfo(camelContext, superclass, strategy);
+                    return superBeanInfo.getMethodInfo(method);
+                }
+            }
+        }
+        return answer;
     }
 
 

Modified: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java?rev=684800&r1=684799&r2=684800&view=diff
==============================================================================
--- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java (original)
+++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java Mon Aug 11 09:31:43 2008
@@ -22,6 +22,7 @@
 import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.List;
+import java.util.ArrayList;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
@@ -51,7 +52,7 @@
         this.bodyParameters = bodyParameters;
         this.hasCustomAnnotation = hasCustomAnnotation;
         this.parametersExpression = createParametersExpression();
-        OneWay oneway = method.getAnnotation(OneWay.class);
+        OneWay oneway = findOneWayAnnotation(method);
         if (oneway != null) {
             pattern = oneway.value();
         }
@@ -94,6 +95,17 @@
         return method;
     }
 
+    /**
+     * Returns the {@link org.apache.camel.ExchangePattern} that should be used when invoking this method. This value
+     * defaults to {@link org.apache.camel.ExchangePattern#InOut} unless some {@link OneWay} annotation is used
+     * to override the message exchange pattern.
+     *
+     * @return the exchange pattern to use for invoking this method.
+     */
+    public ExchangePattern getPattern() {
+        return pattern;
+    }
+
     public Expression getParametersExpression() {
         return parametersExpression;
     }
@@ -169,7 +181,77 @@
         };
     }
 
-    public ExchangePattern getPattern() {
-        return pattern;
+    /**
+     * Finds the oneway annotation in priority order; look for method level annotations first, then the class level annotations,
+     * then super class annotations then interface annotations
+     *
+     * @param method the method on which to search
+     * @return the first matching annotation or none if it is not available
+     */
+    protected OneWay findOneWayAnnotation(Method method) {
+        OneWay answer = method.getAnnotation(OneWay.class);
+        if (answer == null) {
+            Class<?> type = method.getDeclaringClass();
+
+            // lets create the search order of types to scan
+            List<Class<?>> typesToSearch = new ArrayList<Class<?>>();
+            addTypeAndSuperTypes(type, typesToSearch);
+            Class[] interfaces = type.getInterfaces();
+            for (Class anInterface : interfaces) {
+                addTypeAndSuperTypes(anInterface, typesToSearch);
+            }
+
+            // now lets scan for a type which the current declared class overloads
+            answer = findOneWayAnnotationOnMethod(typesToSearch, method);
+            if (answer == null ){
+                answer = findOneWayAnnotation(typesToSearch);
+            }
+        }
+        return answer;
+    }
+
+    /**
+     * Adds the current class and all of its base classes (apart from {@link Object} to the given list
+     * @param type
+     * @param result
+     */
+    protected void addTypeAndSuperTypes(Class<?> type, List<Class<?>> result) {
+        for (Class<?> t = type; t != null && t != Object.class; t = t.getSuperclass()) {
+            result.add(t);
+        }
+    }
+
+    /**
+     * Finds the first annotation on the base methods defined in the list of classes
+     */
+    protected OneWay findOneWayAnnotationOnMethod(List<Class<?>> classes, Method method) {
+        for (Class<?> type : classes) {
+            try {
+                Method definedMethod = type.getMethod(method.getName(), method.getParameterTypes());
+                OneWay answer = definedMethod.getAnnotation(OneWay.class);
+                if (answer != null) {
+                    return answer;
+                }
+            } catch (NoSuchMethodException e) {
+                // ignore
+            }
+        }
+        return null;
+    }
+
+
+    /**
+     * Finds the first annotation on the given list of classes
+     */
+    protected OneWay findOneWayAnnotation(List<Class<?>> classes) {
+        for (Class<?> type : classes) {
+            OneWay answer = type.getAnnotation(OneWay.class);
+            if (answer != null) {
+                return answer;
+            }
+        }
+        return null;
     }
+
+
 }

Copied: activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java (from r684774, activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanInfoTestTest.java)
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java?p2=activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java&p1=activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanInfoTestTest.java&r1=684774&r2=684800&rev=684800&view=diff
==============================================================================
--- activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanInfoTestTest.java (original)
+++ activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java Mon Aug 11 09:31:43 2008
@@ -22,23 +22,74 @@
 import org.apache.camel.ExchangePattern;
 import org.apache.camel.CamelContext;
 import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 import java.lang.reflect.Method;
 
 /**
  * @version $Revision: 1.1 $
  */
-public class BeanInfoTestTest extends TestCase {
+public class BeanInfoTest extends TestCase {
+    private static final transient Log LOG = LogFactory.getLog(BeanInfoTest.class);
+
     protected CamelContext camelContext = new DefaultCamelContext();
-    protected BeanInfo info = new BeanInfo(camelContext, Foo.class);
 
-    public void testMethodPattern() throws Exception {
-        assertMethodPattern("inOutMethod", ExchangePattern.InOut);
-        assertMethodPattern("inOnlyMethod", ExchangePattern.InOnly);
-        assertMethodPattern("robustInOnlyMethod", ExchangePattern.RobustInOnly);
+    public void testMethodPatternUsingMethodAnnotations() throws Exception {
+        BeanInfo info = createBeanInfo(Foo.class);
+
+        assertMethodPattern(info, "inOutMethod", ExchangePattern.InOut);
+        assertMethodPattern(info, "inOnlyMethod", ExchangePattern.InOnly);
+        assertMethodPattern(info, "robustInOnlyMethod", ExchangePattern.RobustInOnly);
+    }
+
+    public void testMethodPatternUsingClassAnnotationsOnInterface() throws Exception {
+        BeanInfo info = createBeanInfo(MyOneWayInterface.class);
+
+        assertMethodPattern(info, "inOnlyMethod", ExchangePattern.InOnly);
+    }
+
+    public void testMethodPatternUsingMethodAnnotationsOnInterface() throws Exception {
+        BeanInfo info = createBeanInfo(MyOneWayInterfaceWithOverloadedMethod.class);
+
+        assertMethodPattern(info, "inOnlyMethod", ExchangePattern.InOnly);
+        assertMethodPattern(info, "robustInOnlyMethod", ExchangePattern.RobustInOnly);
+    }
+
+    public void testMethodPatternUsingClassAnnotationsButOverloadingOnMethod() throws Exception {
+        BeanInfo info = createBeanInfo(OverloadOnMethod.class);
+
+        assertMethodPattern(info, "inOnlyMethod", ExchangePattern.InOnly);
+        assertMethodPattern(info, "robustInOnlyMethod", ExchangePattern.RobustInOnly);
+    }
+
+    public void testMethodPatternUsingClassAnnotationsButOverloadingOnBaseClassMethod() throws Exception {
+        BeanInfo info = createBeanInfo(OverloadOnBaseClass.class);
+
+        assertMethodPattern(info, "inOnlyMethod", ExchangePattern.InOnly);
+        assertMethodPattern(info, "robustInOnlyMethod", ExchangePattern.RobustInOnly);
+    }
+
+    public void testMethodPatternUsingClassAnnotationsOnClassWithAnnotationsOnInterface() throws Exception {
+        BeanInfo info = createBeanInfo(OverloadOnMethod.class);
+
+        assertMethodPattern(info, "inOnlyMethod", ExchangePattern.InOnly);
+        assertMethodPattern(info, "robustInOnlyMethod", ExchangePattern.RobustInOnly);
+    }
+
+    public void testMethodPatternUsingClassAnnotationsOnBaseInterfaceAndOverloadingMethodOnDerivedInterface() throws Exception {
+        BeanInfo info = createBeanInfo(OverloadOnInterface.class);
+
+        assertMethodPattern(info, "inOnlyMethod", ExchangePattern.InOnly);
+        assertMethodPattern(info, "robustInOnlyMethod", ExchangePattern.RobustInOnly);
+    }
+
+    protected BeanInfo createBeanInfo(Class type) {
+        BeanInfo info = new BeanInfo(camelContext, type);
+        return info;
     }
 
-    protected void assertMethodPattern(String methodName, ExchangePattern expectedPattern) throws NoSuchMethodException {
+    protected void assertMethodPattern(BeanInfo info, String methodName, ExchangePattern expectedPattern) throws NoSuchMethodException {
         Class type = info.getType();
         Method method = type.getMethod(methodName);
         assertNotNull("Could not find method: " + methodName, method);
@@ -49,7 +100,7 @@
         ExchangePattern actualPattern = methodInfo.getPattern();
         assertEquals("Pattern for: " + method, expectedPattern, actualPattern);
 
-        //System.out.println("Method: " + method + " has pattern: " + actualPattern);
+        LOG.info("Method: " + method + " has pattern: " + actualPattern);
     }
 
     public interface Foo {
@@ -61,4 +112,42 @@
         @OneWay(ExchangePattern.RobustInOnly)
         public void robustInOnlyMethod();
     }
+
+    @OneWay
+    public interface MyOneWayInterface {
+        public void inOnlyMethod();
+    }
+
+    @OneWay
+    public interface MyOneWayInterfaceWithOverloadedMethod {
+        public void inOnlyMethod();
+
+        @OneWay(ExchangePattern.RobustInOnly)
+        public void robustInOnlyMethod();
+    }
+
+    public static class OverloadOnMethod implements MyOneWayInterface {
+
+        public void inOnlyMethod() {
+        }
+
+        @OneWay(ExchangePattern.RobustInOnly)
+        public void robustInOnlyMethod() {
+        }
+    }
+
+    public static class OverloadOnBaseClass extends OverloadOnMethod {
+        public void robustInOnlyMethod() {
+        }
+    }
+
+    public static class OverloadOnInterface implements MyOneWayInterfaceWithOverloadedMethod {
+
+        public void inOnlyMethod() {
+        }
+
+        public void robustInOnlyMethod() {
+        }
+    }
+
 }

Propchange: activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java
------------------------------------------------------------------------------
    svn:eol-style = native