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")); + } + }; + } + +}