Author: davsclaus
Date: Thu Aug  5 12:43:40 2010
New Revision: 982583

URL: http://svn.apache.org/viewvc?rev=982583&view=rev
Log:
CAMEL-3025: Camel proxy will throw exception based on the proxied method 
declared exception list.

Added:
    
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyApplicationException.java
    
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyService.java
    
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyServiceProxyTest.java
Modified:
    
camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java
    
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyCustomException.java

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java?rev=982583&r1=982582&r2=982583&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java
 Thu Aug  5 12:43:40 2010
@@ -25,6 +25,7 @@ import org.apache.camel.ExchangePattern;
 import org.apache.camel.Producer;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.impl.DefaultExchange;
+import org.apache.camel.util.ObjectHelper;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -64,16 +65,22 @@ public class CamelInvocationHandler impl
         producer.process(exchange);
 
         // check if we had an exception
-        Throwable fault = exchange.getException();
-        if (fault != null) {
-            if (fault instanceof RuntimeCamelException) {
+        Throwable cause = exchange.getException();
+        if (cause != null) {
+            Throwable found = findSuitableException(cause, method);
+            if (found != null) {
+                throw found;
+            }
+            // special for runtime camel exceptions as they can be nested
+            if (cause instanceof RuntimeCamelException) {
                 // if the inner cause is a runtime exception we can throw it 
directly
-                if (fault.getCause() instanceof RuntimeException) {
-                    throw (RuntimeException) ((RuntimeCamelException) 
fault).getCause();
+                if (cause.getCause() instanceof RuntimeException) {
+                    throw (RuntimeException) ((RuntimeCamelException) 
cause).getCause();
                 }
-                throw (RuntimeCamelException) fault;
+                throw (RuntimeCamelException) cause;
             }
-            throw fault;
+            // okay just throw the exception as is
+            throw cause;
         }
 
         // do not return a reply if the method is VOID or the MEP is not OUT 
capable
@@ -96,5 +103,32 @@ public class CamelInvocationHandler impl
         }
         return answer;
     }
+
+    /**
+     * Tries to find the best suited exception to throw.
+     * <p/>
+     * It looks in the exception hierarchy from the caused exception and 
matches this against the declared exceptions
+     * being thrown on the method.
+     *
+     * @param cause   the caused exception
+     * @param method  the method
+     * @return the exception to throw, or <tt>null</tt> if not possible to 
find a suitable exception
+     */
+    protected Throwable findSuitableException(Throwable cause, Method method) {
+        if (method.getExceptionTypes() == null || 
method.getExceptionTypes().length == 0) {
+            return null;
+        }
+
+        // see if there is any exception which matches the declared exception 
on the method
+        for (Class<?> type : method.getExceptionTypes()) {
+            Object fault = ObjectHelper.getException(type, cause);
+            if (fault != null) {
+                return Throwable.class.cast(fault);
+            }
+        }
+
+        return null;
+    }
+
 }
 

Added: 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyApplicationException.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyApplicationException.java?rev=982583&view=auto
==============================================================================
--- 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyApplicationException.java
 (added)
+++ 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyApplicationException.java
 Thu Aug  5 12:43:40 2010
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.bean;
+
+/**
+ * @version $Revision$
+ */
+public class MyApplicationException extends Exception {
+
+    private final int code;
+
+    public MyApplicationException(String message, int code) {
+        super(message);
+        this.code = code;
+    }
+
+    public int getCode() {
+        return code;
+    }
+}

Modified: 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyCustomException.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyCustomException.java?rev=982583&r1=982582&r2=982583&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyCustomException.java
 (original)
+++ 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyCustomException.java
 Thu Aug  5 12:43:40 2010
@@ -21,4 +21,8 @@ public class MyCustomException extends E
     public MyCustomException(String message) {
         super(message);
     }
+
+    public MyCustomException(String message, Throwable cause) {
+        super(message, cause);
+    }
 }

Added: 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyService.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyService.java?rev=982583&view=auto
==============================================================================
--- 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyService.java
 (added)
+++ 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyService.java
 Thu Aug  5 12:43:40 2010
@@ -0,0 +1,26 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.bean;
+
+/**
+ * @version $Revision$
+ */
+public interface MyService {
+
+    String method(String in) throws MyApplicationException;
+
+}

Added: 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyServiceProxyTest.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyServiceProxyTest.java?rev=982583&view=auto
==============================================================================
--- 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyServiceProxyTest.java
 (added)
+++ 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MyServiceProxyTest.java
 Thu Aug  5 12:43:40 2010
@@ -0,0 +1,93 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.bean;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.builder.RouteBuilder;
+
+/**
+ * @version $Revision$
+ */
+public class MyServiceProxyTest extends ContextTestSupport {
+
+    public void testOk() throws Exception {
+        MyService myService = 
ProxyHelper.createProxy(context.getEndpoint("direct:start"), MyService.class);
+        String reply = myService.method("Hello World");
+        assertEquals("Camel in Action", reply);
+    }
+
+    public void testKaboom() throws Exception {
+        MyService myService = 
ProxyHelper.createProxy(context.getEndpoint("direct:start"), MyService.class);
+        try {
+            myService.method("Kaboom");
+            fail("Should have thrown exception");
+        } catch (IllegalArgumentException e) {
+            assertEquals("Damn", e.getMessage());
+        }
+    }
+
+    public void testCheckedException() throws Exception {
+        MyService myService = 
ProxyHelper.createProxy(context.getEndpoint("direct:start"), MyService.class);
+        try {
+            myService.method("Tiger in Action");
+            fail("Should have thrown exception");
+        } catch (MyApplicationException e) {
+            assertEquals("No tigers", e.getMessage());
+            assertEquals(9, e.getCode());
+        }
+    }
+
+    public void testNestedRuntimeCheckedException() throws Exception {
+        MyService myService = 
ProxyHelper.createProxy(context.getEndpoint("direct:start"), MyService.class);
+        try {
+            myService.method("Donkey in Action");
+            fail("Should have thrown exception");
+        } catch (MyApplicationException e) {
+            assertEquals("No donkeys", e.getMessage());
+            assertEquals(8, e.getCode());
+        }
+    }
+
+    public void testNestedCheckedCheckedException() throws Exception {
+        MyService myService = 
ProxyHelper.createProxy(context.getEndpoint("direct:start"), MyService.class);
+        try {
+            myService.method("Elephant in Action");
+            fail("Should have thrown exception");
+        } catch (MyApplicationException e) {
+            assertEquals("No elephants", e.getMessage());
+            assertEquals(7, e.getCode());
+        }
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                    .choice()
+                        .when(body().isEqualTo("Tiger in 
Action")).throwException(new MyApplicationException("No tigers", 9))
+                        .when(body().isEqualTo("Donkey in 
Action")).throwException(new RuntimeCamelException(new 
MyApplicationException("No donkeys", 8)))
+                        .when(body().isEqualTo("Elephant in 
Action")).throwException(new MyCustomException("Damn", new 
MyApplicationException("No elephants", 7)))
+                        .when(body().isEqualTo("Kaboom")).throwException(new 
IllegalArgumentException("Damn"))
+                        .otherwise().transform(constant("Camel in Action"));
+            }
+        };
+    }
+
+}


Reply via email to