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 2008/12/04 14:27:12 UTC
svn commit: r723314 - in /activemq/camel/trunk/camel-core/src:
main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
test/java/org/apache/camel/processor/onexception/OnExceptionWrappedExceptionTest.java
Author: davsclaus
Date: Thu Dec 4 05:27:12 2008
New Revision: 723314
URL: http://svn.apache.org/viewvc?rev=723314&view=rev
Log:
CAMEL-1144: DefaultExceptionPolicyStrategy now tests caused by exceptions (using bottom to top exception hieracy iterator)
Added:
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionWrappedExceptionTest.java (contents, props changed)
- copied, changed from r723229, activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionRouteTest.java
Modified:
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
Modified: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java?rev=723314&r1=723313&r2=723314&view=diff
==============================================================================
--- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java (original)
+++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java Thu Dec 4 05:27:12 2008
@@ -18,6 +18,10 @@
import java.util.Map;
import java.util.Set;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
import org.apache.camel.Exchange;
import org.apache.camel.model.ExceptionType;
@@ -31,11 +35,13 @@
* <b>Selection strategy:</b>
* <br/>This strategy applies the following rules:
* <ul>
- * <li>The exception type must be configured with an Exception that is an instance of the thrown exception, this
- * is tested using the {@link #filter(org.apache.camel.model.ExceptionType, Class, Throwable)} method. </li>
- * <li>If the exception type has exactly the thrown exception then its selected as its an exact match</li>
- * <li>Otherwise the type that has an exception that is the closests super of the thrown exception is selected
- * (recurring up the exception hierarchy)</li>
+ * <li>Will walk the exception hieracy from bottom upwards till the thrown exception, meaning that the most outer caused
+ * by is selected first, ending with the thrown exception itself</li>
+ * <li>The exception type must be configured with an Exception that is an instance of the thrown exception, this
+ * is tested using the {@link #filter(org.apache.camel.model.ExceptionType, Class, Throwable)} method. </li>
+ * <li>If the exception type has exactly the thrown exception then its selected as its an exact match</li>
+ * <li>Otherwise the type that has an exception that is the closests super of the thrown exception is selected
+ * (recurring up the exception hierarchy)</li>
* </ul>
* <p/>
* <b>Fine grained matching:</b>
@@ -50,6 +56,22 @@
public ExceptionType getExceptionPolicy(Map<ExceptionPolicyKey, ExceptionType> exceptionPolicices, Exchange exchange,
Throwable exception) {
+
+ // recursive up the tree using the iterator
+ Iterator<Throwable> it = new ExceptionIterator(exception);
+ while (it.hasNext()) {
+ ExceptionType type = doGetExceptionPolicy(exceptionPolicices, exchange, it.next());
+ if (type != null) {
+ return type;
+ }
+ }
+
+ // no type found
+ return null;
+ }
+
+ private ExceptionType doGetExceptionPolicy(Map<ExceptionPolicyKey, ExceptionType> exceptionPolicices, Exchange exchange,
+ Throwable exception) {
if (LOG.isDebugEnabled()) {
LOG.debug("Finding best suited exception policy for thrown exception " + exception.getClass().getName());
}
@@ -109,10 +131,10 @@
/**
* Strategy to filter the given type exception class with the thrown exception
*
- * @param type the exception type
- * @param exceptionClass the current exception class for testing
- * @param exception the thrown exception
- * @return <tt>true</tt> if the to current exception class is a candidate, <tt>false</tt> to skip it.
+ * @param type the exception type
+ * @param exceptionClass the current exception class for testing
+ * @param exception the thrown exception
+ * @return <tt>true</tt> if the to current exception class is a candidate, <tt>false</tt> to skip it.
*/
protected boolean filter(ExceptionType type, Class exceptionClass, Throwable exception) {
// must be instance of check to ensure that the exceptionClass is one type of the thrown exception
@@ -124,12 +146,12 @@
* <p/>
* This default implementation will match as:
* <ul>
- * <li>Always true if no when predicate on the exception type
- * <li>Otherwise the when predicate is matches against the current exchange
+ * <li>Always true if no when predicate on the exception type
+ * <li>Otherwise the when predicate is matches against the current exchange
* </ul>
*
- * @param type the exception type
- * @param exchange the current {@link Exchange}
+ * @param type the exception type
+ * @param exchange the current {@link Exchange}
* @return <tt>true</tt> if matched, <tt>false</tt> otherwise.
*/
protected boolean matchesWhen(ExceptionType type, Exchange exchange) {
@@ -147,4 +169,40 @@
return 1 + getInheritanceLevel(clazz.getSuperclass());
}
+ /**
+ * Iterator that walks the exception hieracy in the order we should match.
+ * <p/>
+ * Will default walk from bottom upwards to the root exception
+ */
+ protected class ExceptionIterator implements Iterator<Throwable> {
+ private List<Throwable> tree = new ArrayList<Throwable>();
+ private Iterator<Throwable> it;
+
+ public ExceptionIterator(Throwable exception) {
+ Throwable current = exception;
+ // spool to the bottom of the caused by tree
+ while (current != null) {
+ tree.add(current);
+ current = current.getCause();
+ }
+
+ // reverse tree so we go from bottom to top
+ Collections.reverse(tree);
+ it = tree.iterator();
+ }
+
+ public boolean hasNext() {
+ return it.hasNext();
+ }
+
+ public Throwable next() {
+ return it.next();
+ }
+
+ public void remove() {
+ it.remove();
+ }
+ }
+
+
}
Copied: activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionWrappedExceptionTest.java (from r723229, activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionRouteTest.java)
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionWrappedExceptionTest.java?p2=activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionWrappedExceptionTest.java&p1=activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionRouteTest.java&r1=723229&r2=723314&rev=723314&view=diff
==============================================================================
--- activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionRouteTest.java (original)
+++ activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionWrappedExceptionTest.java Thu Dec 4 05:27:12 2008
@@ -17,116 +17,55 @@
package org.apache.camel.processor.onexception;
import org.apache.camel.ContextTestSupport;
-import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.Exchange;
+import org.apache.camel.TypeConverter;
import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.impl.JndiRegistry;
+import static org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException;
/**
- * Unit test inspired by user forum.
+ * Unit test to test that onException handles wrapped exceptions
*/
-public class OnExceptionRouteTest extends ContextTestSupport {
+public class OnExceptionWrappedExceptionTest extends ContextTestSupport {
- private MyOwnHandlerBean myOwnHandlerBean;
- private MyServiceBean myServiceBean;
-
- public void testNoError() throws Exception {
+ public void testWrappedException() throws Exception {
getMockEndpoint("mock:error").expectedMessageCount(0);
+ getMockEndpoint("mock:wrapped").expectedMessageCount(1);
+ getMockEndpoint("mock:end").expectedMessageCount(0);
- MockEndpoint mock = getMockEndpoint("mock:result");
- mock.expectedMessageCount(1);
-
- template.sendBody("direct:start", "<order><type>myType</type><user>James</user></order>");
+ template.sendBody("direct:start", "Hello World");
assertMockEndpointsSatisfied();
}
- public void testFunctionalError() throws Exception {
- getMockEndpoint("mock:error").expectedMessageCount(0);
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ context.getTypeConverterRegistry().addTypeConverter(LocalDateTime.class, String.class, new MyLocalDateTimeConverter());
- MockEndpoint mock = getMockEndpoint("mock:result");
- mock.expectedMessageCount(0);
+ errorHandler(deadLetterChannel("mock:error"));
- template.sendBody("direct:start", "<order><type>myType</type><user>Func</user></order>");
+ onException(IllegalArgumentException.class).handled(true).to("mock:wrapped");
- assertMockEndpointsSatisfied();
- assertEquals("<order><type>myType</type><user>Func</user></order>", myOwnHandlerBean.getPayload());
+ from("direct:start").convertBodyTo(LocalDateTime.class).to("mock:end");
+ }
+ };
}
- public void testTechnicalError() throws Exception {
- getMockEndpoint("mock:error").expectedMessageCount(1);
-
- MockEndpoint mock = getMockEndpoint("mock:result");
- mock.expectedMessageCount(0);
-
- template.sendBody("direct:start", "<order><type>myType</type><user>Tech</user></order>");
-
- assertMockEndpointsSatisfied();
- // should not handle it
- assertNull(myOwnHandlerBean.getPayload());
+ public static class LocalDateTime {
}
- public void testErrorWhileHandlingException() throws Exception {
- getMockEndpoint("mock:error").expectedMessageCount(0);
-
- MockEndpoint mock = getMockEndpoint("mock:result");
- mock.expectedMessageCount(0);
+ private class MyLocalDateTimeConverter implements TypeConverter {
- try {
- template.sendBody("direct:start", "<order><type>myType</type><user>FuncError</user></order>");
- fail("Should throw a RuntimeCamelException");
- } catch (RuntimeCamelException e) {
- assertEquals("Damm something did not work", e.getCause().getMessage());
+ public <T> T convertTo(Class<T> type, Object value) {
+ // simulate @Converter where we wrap thrown exception in RuntimeCamelException
+ throw wrapRuntimeCamelException(new IllegalArgumentException("Bad Data"));
}
- assertMockEndpointsSatisfied();
- // should not handle it
- assertNull(myOwnHandlerBean.getPayload());
- }
-
- @Override
- protected void setUp() throws Exception {
- myOwnHandlerBean = new MyOwnHandlerBean();
- myServiceBean = new MyServiceBean();
- super.setUp();
- }
-
- @Override
- protected JndiRegistry createRegistry() throws Exception {
- JndiRegistry jndi = super.createRegistry();
- jndi.bind("myOwnHandler", myOwnHandlerBean);
- jndi.bind("myServiceBean", myServiceBean);
- return jndi;
- }
-
- @Override
- protected RouteBuilder createRouteBuilder() throws Exception {
- return new RouteBuilder() {
- @Override
- public void configure() throws Exception {
- // default should errors go to mock:error
- errorHandler(deadLetterChannel("mock:error"));
-
- // START SNIPPET: e1
- // if a MyTechnicalException is thrown we will not try to redeliver and we mark it as handled
- // so the caller does not get a failure
- // since we have no to then the exchange will continue to be routed to the normal error handler
- // destination that is mock:error as defined above
- onException(MyTechnicalException.class).maximumRedeliveries(0).handled(true);
-
- // if a MyFunctionalException is thrown we do not want Camel to redelivery but handle it our self using
- // our bean myOwnHandler, then the exchange is not routed to the default error (mock:error)
- onException(MyFunctionalException.class).maximumRedeliveries(0).handled(true).to("bean:myOwnHandler");
-
- // here we route message to our service bean
- from("direct:start").choice()
- .when().xpath("//type = 'myType'")
- .to("bean:myServiceBean")
- // END SNIPPET: e1
- .to("mock:result");
- }
- };
+ public <T> T convertTo(Class<T> type, Exchange exchange, Object value) {
+ return convertTo(type, value);
+ }
}
-
-}
+}
\ No newline at end of file
Propchange: activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionWrappedExceptionTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionWrappedExceptionTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Propchange: activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionWrappedExceptionTest.java
------------------------------------------------------------------------------
svn:mergeinfo =