Author: davsclaus
Date: Sat Apr 5 03:23:36 2008
New Revision: 645063
URL: http://svn.apache.org/viewvc?rev=645063&view=rev
Log:
CAMEL-410
- Fixed bug and applied part of patches from Dan Dudley. Thanks a lot Dan.
- Introduced ExceptionPolicyStrategy to configure if/how exceptintype should
handle a thrown exception.
- Changed the default behaviour of Camel to be smarter, see javadoc for
DefaultExceptionPolicyStrategy.
Added:
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ExceptionBuilderTest.java
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/ErrorHandlerSupportTest.java
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java
Modified:
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ErrorHandlerSupport.java
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ErrorHandlerTest.java
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelTest.java
Modified:
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java?rev=645063&r1=645062&r2=645063&view=diff
==============================================================================
---
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java
(original)
+++
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java
Sat Apr 5 03:23:36 2008
@@ -23,6 +23,8 @@
import org.apache.camel.processor.LoggingLevel;
import org.apache.camel.processor.RecipientList;
import org.apache.camel.processor.RedeliveryPolicy;
+import org.apache.camel.processor.ErrorHandlerSupport;
+import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -35,6 +37,7 @@
*/
public class DeadLetterChannelBuilder extends ErrorHandlerBuilderSupport {
private RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
+ private ExceptionPolicyStrategy exceptionPolicyStrategy =
ErrorHandlerSupport.createDefaultExceptionPolicyStrategy();
private ProcessorFactory deadLetterFactory;
private Processor defaultDeadLetterEndpoint;
private Expression defaultDeadLetterEndpointExpression;
@@ -60,7 +63,7 @@
public Processor createErrorHandler(Processor processor) throws Exception {
Processor deadLetter = getDeadLetterFactory().createProcessor();
- DeadLetterChannel answer = new DeadLetterChannel(processor,
deadLetter, getRedeliveryPolicy(), getLogger());
+ DeadLetterChannel answer = new DeadLetterChannel(processor,
deadLetter, getRedeliveryPolicy(), getLogger(), getExceptionPolicyStrategy());
configure(answer);
return answer;
}
@@ -135,6 +138,14 @@
return log(LogFactory.getLog(log));
}
+ /**
+ * Sets the exception policy to use
+ */
+ public ErrorHandlerBuilderSupport
exceptionPolicyStrategy(ExceptionPolicyStrategy exceptionPolicyStrategy) {
+ setExceptionPolicyStrategy(exceptionPolicyStrategy);
+ return this;
+ }
+
// Properties
//
-------------------------------------------------------------------------
public RedeliveryPolicy getRedeliveryPolicy() {
@@ -220,4 +231,17 @@
public void setLogger(Logger logger) {
this.logger = logger;
}
+
+ /**
+ * Sets the exception policy strategy to use for resolving the [EMAIL
PROTECTED] org.apache.camel.model.ExceptionType}
+ * to use for a given thrown exception
+ */
+ public ExceptionPolicyStrategy getExceptionPolicyStrategy() {
+ return exceptionPolicyStrategy;
+ }
+
+ public void setExceptionPolicyStrategy(ExceptionPolicyStrategy
exceptionPolicyStrategy) {
+ this.exceptionPolicyStrategy = exceptionPolicyStrategy;
+ }
+
}
Modified:
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java?rev=645063&r1=645062&r2=645063&view=diff
==============================================================================
---
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java
(original)
+++
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java
Sat Apr 5 03:23:36 2008
@@ -23,6 +23,7 @@
import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.Processor;
+import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
import org.apache.camel.impl.converter.AsyncProcessorTypeConverter;
import org.apache.camel.model.ExceptionType;
import org.apache.camel.util.AsyncProcessorHelper;
@@ -62,16 +63,18 @@
private Logger logger;
public DeadLetterChannel(Processor output, Processor deadLetter) {
- this(output, deadLetter, new RedeliveryPolicy(),
DeadLetterChannel.createDefaultLogger());
+ this(output, deadLetter, new RedeliveryPolicy(),
DeadLetterChannel.createDefaultLogger(),
+ ErrorHandlerSupport.createDefaultExceptionPolicyStrategy());
}
- public DeadLetterChannel(Processor output, Processor deadLetter,
RedeliveryPolicy redeliveryPolicy, Logger logger) {
+ public DeadLetterChannel(Processor output, Processor deadLetter,
RedeliveryPolicy redeliveryPolicy, Logger logger, ExceptionPolicyStrategy
exceptionPolicyStrategy) {
this.deadLetter = deadLetter;
this.output = output;
this.outputAsync = AsyncProcessorTypeConverter.convert(output);
this.redeliveryPolicy = redeliveryPolicy;
this.logger = logger;
+ setExceptionPolicy(exceptionPolicyStrategy);
}
public static <E extends Exchange> Logger createDefaultLogger() {
@@ -163,7 +166,7 @@
callback.done(true);
return true;
}
- // error occured so loop back around.....
+ // error occurred so loop back around.....
}
}
@@ -261,7 +264,7 @@
Thread.sleep(redeliveryDelay);
} catch (InterruptedException e) {
if (LOG.isDebugEnabled()) {
- LOG.debug("Thread interupted: " + e, e);
+ LOG.debug("Thread interrupted: " + e, e);
}
}
}
Modified:
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ErrorHandlerSupport.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ErrorHandlerSupport.java?rev=645063&r1=645062&r2=645063&view=diff
==============================================================================
---
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ErrorHandlerSupport.java
(original)
+++
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/ErrorHandlerSupport.java
Sat Apr 5 03:23:36 2008
@@ -16,21 +16,25 @@
*/
package org.apache.camel.processor;
-import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.impl.ServiceSupport;
import org.apache.camel.model.ExceptionType;
+import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
+import
org.apache.camel.processor.exceptionpolicy.DefaultExceptionPolicyStrategy;
/**
+ * Support class for [EMAIL PROTECTED] ErrorHandler} implementations.
+ *
* @version $Revision$
*/
public abstract class ErrorHandlerSupport extends ServiceSupport implements
ErrorHandler {
- private Map<Class, ExceptionType> exceptionPolicices = new
IdentityHashMap<Class, ExceptionType>();
+ private Map<Class, ExceptionType> exceptionPolicies = new
LinkedHashMap<Class, ExceptionType>();
+ private ExceptionPolicyStrategy exceptionPolicy =
createDefaultExceptionPolicyStrategy();
public void addExceptionPolicy(ExceptionType exception) {
Processor processor = exception.getErrorHandler();
@@ -39,7 +43,7 @@
List<Class> list = exception.getExceptionClasses();
for (Class exceptionType : list) {
- exceptionPolicices.put(exceptionType, exception);
+ exceptionPolicies.put(exceptionType, exception);
}
}
@@ -48,22 +52,44 @@
*/
protected boolean customProcessorForException(Exchange exchange, Throwable
exception) throws Exception {
ExceptionType policy = getExceptionPolicy(exchange, exception);
- Processor processor = policy.getErrorHandler();
- if (processor != null) {
- processor.process(exchange);
- return true;
+ if (policy != null) {
+ Processor processor = policy.getErrorHandler();
+ if (processor != null) {
+ processor.process(exchange);
+ return true;
+ }
}
return false;
}
+ /**
+ * Attempts to find the best suited [EMAIL PROTECTED] ExceptionType} to be
used for handling the given thrown exception.
+ *
+ * @param exchange the exchange
+ * @param exception the exception that was thrown
+ * @return the best exception type to handle this exception, <tt>null</tt>
if none found.
+ */
protected ExceptionType getExceptionPolicy(Exchange exchange, Throwable
exception) {
- Set<Map.Entry<Class, ExceptionType>> entries =
exceptionPolicices.entrySet();
- for (Map.Entry<Class, ExceptionType> entry : entries) {
- Class type = entry.getKey();
- if (type.isInstance(exception)) {
- return entry.getValue();
- }
+ if (exceptionPolicy == null) {
+ throw new IllegalStateException("The exception policy has not been
set");
}
- return null;
+
+ return exceptionPolicy.getExceptionPolicy(exceptionPolicies, exchange,
exception);
+ }
+
+ /**
+ * Sets the strategy to use for resolving the [EMAIL PROTECTED]
ExceptionType} to use
+ * for handling thrown exceptions.
+ */
+ public void setExceptionPolicy(ExceptionPolicyStrategy exceptionPolicy) {
+ this.exceptionPolicy = exceptionPolicy;
}
+
+ /**
+ * Creates the default exception policy strategy to use.
+ */
+ public static ExceptionPolicyStrategy
createDefaultExceptionPolicyStrategy() {
+ return new DefaultExceptionPolicyStrategy();
+ }
+
}
Added:
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=645063&view=auto
==============================================================================
---
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
(added)
+++
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
Sat Apr 5 03:23:36 2008
@@ -0,0 +1,85 @@
+/**
+ * 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.processor.exceptionpolicy;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.model.ExceptionType;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * The default strategy used in Camel to resolve the [EMAIL PROTECTED]
org.apache.camel.model.ExceptionType} that should
+ * handle the thrown exception.
+ * <p/>
+ * 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</li>
+ * <li>If the exception type has exactly the thrown exception then its
selected</li>
+ * <li>Otherwise the type that has an exception that is super of the thrown
exception is selected
+ * (recurring up the exception hierarchy)
+ * </ul>
+ */
+public class DefaultExceptionPolicyStrategy implements ExceptionPolicyStrategy
{
+
+ private static final transient Log LOG =
LogFactory.getLog(DefaultExceptionPolicyStrategy.class);
+
+ public ExceptionType getExceptionPolicy(Map<Class, ExceptionType>
exceptionPolicices, Exchange exchange,
+ Throwable exception) {
+ // the goal is to find the exception with the same/closet inheritance
level as the target exception being thrown
+ int targetLevel = getInheritanceLevel(exception.getClass());
+ // candidate is the best candidate found so far
+ ExceptionType candidate = null;
+ // difference in inheritance level between the current candidate and
the thrown exception (target level)
+ int candidateDiff = Integer.MAX_VALUE;
+
+ // loop through all the entries and find the best candidates to use
+ Set<Map.Entry<Class, ExceptionType>> entries =
exceptionPolicices.entrySet();
+ for (Map.Entry<Class, ExceptionType> entry : entries) {
+ Class clazz = entry.getKey();
+ ExceptionType type = entry.getValue();
+
+ // must be instance of check to ensure that the clazz is one type
of the thrown exception
+ if (clazz.isInstance(exception)) {
+ int level = getInheritanceLevel(clazz);
+ int diff = targetLevel - level;
+
+ if (diff < candidateDiff) {
+ // replace with a much better candidate
+ candidate = type;
+ candidateDiff = diff;
+ }
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Using " + candidate + " as the exception policy");
+ }
+ return candidate;
+
+ }
+
+ private static int getInheritanceLevel(Class clazz) {
+ if (clazz == null || "java.lang.Object".equals(clazz.getName())) {
+ return 0;
+ }
+ return 1 + getInheritanceLevel(clazz.getSuperclass());
+ }
+
+}
Added:
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java?rev=645063&view=auto
==============================================================================
---
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java
(added)
+++
activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java
Sat Apr 5 03:23:36 2008
@@ -0,0 +1,43 @@
+/**
+ * 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.processor.exceptionpolicy;
+
+import java.util.Map;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.model.ExceptionType;
+
+/**
+ * A strategy to determine witch [EMAIL PROTECTED]
org.apache.camel.model.ExceptionType} should handle the thrown
+ * exception.
+ *
+ * @see
org.apache.camel.processor.exceptionpolicy.DefaultExceptionPolicyStrategy
DefaultExceptionPolicy
+ */
+public interface ExceptionPolicyStrategy {
+
+ /**
+ * Resolves the [EMAIL PROTECTED] org.apache.camel.model.ExceptionType}
that should handle the thrown exception.
+ *
+ * @param exceptionPolicices the configured exception policies to resolve
from
+ * @param exchange the exchange
+ * @param exception the exception that was thrown
+ * @return the resolved exception type to handle this exception,
<tt>null</tt> if none found.
+ */
+ public ExceptionType getExceptionPolicy(Map<Class, ExceptionType>
exceptionPolicices, Exchange exchange,
+ Throwable exception);
+
+}
Modified:
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ErrorHandlerTest.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ErrorHandlerTest.java?rev=645063&r1=645062&r2=645063&view=diff
==============================================================================
---
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ErrorHandlerTest.java
(original)
+++
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ErrorHandlerTest.java
Sat Apr 5 03:23:36 2008
@@ -60,7 +60,7 @@
}
}
- public void testOverloadingTheHandlerOnASingleRoute() throws Exception {
+ public void testOverloadingTheHandlerOnASingleRoute() throws Exception {
// START SNIPPET: e2
RouteBuilder builder = new RouteBuilder() {
@@ -174,4 +174,5 @@
log.debug("Found sendProcessor: " + sendProcessor);
}
}
+
}
Added:
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ExceptionBuilderTest.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ExceptionBuilderTest.java?rev=645063&view=auto
==============================================================================
---
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ExceptionBuilderTest.java
(added)
+++
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/ExceptionBuilderTest.java
Sat Apr 5 03:23:36 2008
@@ -0,0 +1,156 @@
+/**
+ * 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.builder;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.security.GeneralSecurityException;
+import java.security.KeyException;
+import java.security.KeyManagementException;
+
+import org.apache.camel.CamelExchangeException;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.component.mock.MockEndpoint;
+
+/**
+ * Unit test to test exception configuration
+ */
+public class ExceptionBuilderTest extends ContextTestSupport {
+
+ private static final String MESSAGE_INFO = "messageInfo";
+ private static final String errorQueue = "mock:error";
+ private static final String businessErrorQueue = "mock:badBusiness";
+ private static final String securityErrorQueue = "mock:securitError";
+
+ public void testNPE() throws Exception {
+ MockEndpoint mock = getMockEndpoint(errorQueue);
+ mock.expectedMessageCount(1);
+ mock.expectedHeaderReceived(MESSAGE_INFO, "Damm a NPE");
+
+ template.sendBody("direct:a", "Hello NPE");
+
+ mock.assertIsSatisfied();
+ }
+
+ public void testIOException() throws Exception {
+ MockEndpoint mock = getMockEndpoint(errorQueue);
+ mock.expectedMessageCount(1);
+ mock.expectedHeaderReceived(MESSAGE_INFO, "Damm somekind of IO
exception");
+
+ template.sendBody("direct:a", "Hello IO");
+
+ mock.assertIsSatisfied();
+ }
+
+ public void testException() throws Exception {
+ MockEndpoint mock = getMockEndpoint(errorQueue);
+ mock.expectedMessageCount(1);
+ mock.expectedHeaderReceived(MESSAGE_INFO, "Damm just exception");
+
+ template.sendBody("direct:a", "Hello Exception");
+
+ mock.assertIsSatisfied();
+ }
+
+ public void testMyBusinessException() throws Exception {
+ MockEndpoint mock = getMockEndpoint(businessErrorQueue);
+ mock.expectedMessageCount(1);
+ mock.expectedHeaderReceived(MESSAGE_INFO, "Damm my business is not
going to well");
+
+ template.sendBody("direct:a", "Hello business");
+
+ mock.assertIsSatisfied();
+ }
+
+ public void testSecurityConfiguredWithTwoExceptions() throws Exception {
+ // test that we also handles a configuration with 2 or more exceptions
+ MockEndpoint mock = getMockEndpoint(securityErrorQueue);
+ mock.expectedMessageCount(1);
+ mock.expectedHeaderReceived(MESSAGE_INFO, "Damm some security error");
+
+ template.sendBody("direct:a", "I am not allowed to do this");
+
+ mock.assertIsSatisfied();
+ }
+
+ public static class MyBaseBusinessException extends Exception {
+ }
+
+ public static class MyBusinessException extends MyBaseBusinessException {
+ }
+
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ public void configure() throws Exception {
+ // START SNIPPET: exceptionBuilder1
+ exception(NullPointerException.class)
+ .maximumRedeliveries(1)
+ .setHeader(MESSAGE_INFO, "Damm a NPE")
+ .to(errorQueue);
+
+ exception(IOException.class)
+ .initialRedeliveryDelay(5000L)
+ .maximumRedeliveries(3)
+ .backOffMultiplier(1.0)
+ .useExponentialBackOff()
+ .setHeader(MESSAGE_INFO, "Damm somekind of IO exception")
+ .to(errorQueue);
+
+ exception(Exception.class)
+ .initialRedeliveryDelay(1000L)
+ .maximumRedeliveries(2)
+ .setHeader(MESSAGE_INFO, "Damm just exception")
+ .to(errorQueue);
+ // END SNIPPET: exceptionBuilder1
+
+ exception(MyBaseBusinessException.class)
+ .initialRedeliveryDelay(1000L)
+ .maximumRedeliveries(3)
+ .setHeader(MESSAGE_INFO, "Damm my business is not going to
well")
+ .to(businessErrorQueue);
+
+
exception(GeneralSecurityException.class).exception(KeyException.class)
+ .maximumRedeliveries(1)
+ .setHeader(MESSAGE_INFO, "Damm some security error")
+ .to(securityErrorQueue);
+
+
+ from("direct:a").process(new Processor() {
+ public void process(Exchange exchange) throws Exception {
+ String s = exchange.getIn().getBody(String.class);
+ if ("Hello NPE".equals(s)) {
+ throw new NullPointerException();
+ } else if ("Hello IO".equals(s)) {
+ throw new ConnectException("Forced for testing -
can not connect to remote server");
+ } else if ("Hello Exception".equals(s)) {
+ throw new CamelExchangeException("Forced for
testing", exchange);
+ } else if ("Hello business".equals(s)) {
+ throw new MyBusinessException();
+ } else if ("I am not allowed to do this".equals(s)) {
+ throw new KeyManagementException();
+ }
+ exchange.getOut().setBody("Hello World");
+ }
+ }).to("mock:result");
+ }
+ };
+ }
+
+}
+
Modified:
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelTest.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelTest.java?rev=645063&r1=645062&r2=645063&view=diff
==============================================================================
---
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelTest.java
(original)
+++
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelTest.java
Sat Apr 5 03:23:36 2008
@@ -23,14 +23,12 @@
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
-import static org.apache.camel.component.mock.MockEndpoint.assertIsSatisfied;
-
/**
* @version $Revision$
*/
public class DeadLetterChannelTest extends ContextTestSupport {
protected Endpoint<Exchange> startEndpoint;
- protected MockEndpoint deadEndpoint;
+ protected MockEndpoint deadEndpoint;
protected MockEndpoint successEndpoint;
protected int failUntilAttempt = 2;
protected String body = "<hello>world!</hello>";
@@ -88,18 +86,13 @@
return new RouteBuilder() {
public void configure() {
from("direct:start").errorHandler(
-
deadLetterChannel("mock:failed").maximumRedeliveries(2)
-
.initialRedeliveryDelay(1)
-
.loggingLevel(LoggingLevel.DEBUG)
+ deadLetterChannel("mock:failed").maximumRedeliveries(2)
+ .initialRedeliveryDelay(1)
+ .loggingLevel(LoggingLevel.DEBUG)
).process(processor);
-
- /*
- * TODO - currently process().to() results in two separate
- * operations which have their own error handler
- *
- * .to("mock:success");
- */
+ // TODO - currently process().to() results in two separate
operations which have their own error handler
+ // to("mock:success");
}
};
}
Added:
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/ErrorHandlerSupportTest.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/ErrorHandlerSupportTest.java?rev=645063&view=auto
==============================================================================
---
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/ErrorHandlerSupportTest.java
(added)
+++
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/ErrorHandlerSupportTest.java
Sat Apr 5 03:23:36 2008
@@ -0,0 +1,94 @@
+/**
+ * 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.processor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.model.ExceptionType;
+
+public class ErrorHandlerSupportTest extends TestCase {
+
+ public void testOnePolicyChildFirst() {
+ List<Class> exceptions = new ArrayList<Class>();
+ exceptions.add(ChildException.class);
+ exceptions.add(ParentException.class);
+
+ ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
+ support.addExceptionPolicy(new ExceptionType(exceptions));
+
+ assertEquals(ChildException.class, getExceptionPolicyFor(support, new
ChildException(), 0));
+ assertEquals(ParentException.class, getExceptionPolicyFor(support, new
ParentException(), 1));
+ }
+
+ public void testOnePolicyChildLast() {
+ List<Class> exceptions = new ArrayList<Class>();
+ exceptions.add(ParentException.class);
+ exceptions.add(ChildException.class);
+
+ ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
+ support.addExceptionPolicy(new ExceptionType(exceptions));
+
+ assertEquals(ChildException.class, getExceptionPolicyFor(support, new
ChildException(), 1));
+ assertEquals(ParentException.class, getExceptionPolicyFor(support, new
ParentException(), 0));
+ }
+
+ public void testTwoPolicyChildFirst() {
+ ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
+ support.addExceptionPolicy(new ExceptionType(ChildException.class));
+ support.addExceptionPolicy(new ExceptionType(ParentException.class));
+
+ assertEquals(ChildException.class, getExceptionPolicyFor(support, new
ChildException(), 0));
+ assertEquals(ParentException.class, getExceptionPolicyFor(support, new
ParentException(), 0));
+ }
+
+ public void testTwoPolicyChildLast() {
+ ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
+ support.addExceptionPolicy(new ExceptionType(ParentException.class));
+ support.addExceptionPolicy(new ExceptionType(ChildException.class));
+
+ assertEquals(ChildException.class, getExceptionPolicyFor(support, new
ChildException(), 0));
+ assertEquals(ParentException.class, getExceptionPolicyFor(support, new
ParentException(), 0));
+ }
+
+ private static Class getExceptionPolicyFor(ErrorHandlerSupport support,
Throwable childException,
+ int index) {
+ return support.getExceptionPolicy(null,
childException).getExceptionClasses().get(index);
+ }
+
+ private static class ParentException extends Exception {
+ }
+
+ private static class ChildException extends ParentException {
+ }
+
+ private static class ShuntErrorHandlerSupport extends ErrorHandlerSupport {
+
+ protected void doStart() throws Exception {
+ }
+
+ protected void doStop() throws Exception {
+ }
+
+ public void process(Exchange exchange) throws Exception {
+ }
+ }
+
+}
Added:
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java?rev=645063&view=auto
==============================================================================
---
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
(added)
+++
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
Sat Apr 5 03:23:36 2008
@@ -0,0 +1,95 @@
+/**
+ * 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.processor.exceptionpolicy;
+
+import java.util.Map;
+
+import org.apache.camel.CamelException;
+import org.apache.camel.CamelExchangeException;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.model.ExceptionType;
+
+/**
+ * Unit test with a user plugged in exception policy to use instead of default.
+ */
+public class CustomExceptionPolicyStrategyTest extends ContextTestSupport {
+
+ private static final String MESSAGE_INFO = "messageInfo";
+ private static final String errorQueue = "mock:error";
+
+ public static class MyPolicyException extends Exception {
+ }
+
+ public static class MyPolicy implements ExceptionPolicyStrategy {
+
+ public ExceptionType getExceptionPolicy(Map<Class, ExceptionType>
exceptionPolicices,
+ Exchange exchange,
+ Throwable exception) {
+ // We forced a CamelException in the test below but our custom
policy will
+ // override and let MyPolicyException handle it instead
+ return exceptionPolicices.get(MyPolicyException.class);
+ }
+ }
+
+
+
+ public void testCustomPolicy() throws Exception {
+ MockEndpoint mock = getMockEndpoint(errorQueue);
+ mock.expectedMessageCount(1);
+ mock.expectedHeaderReceived(MESSAGE_INFO, "Damm my policy exception");
+
+ template.sendBody("direct:a", "Hello Camel");
+
+ mock.assertIsSatisfied();
+ }
+
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ public void configure() throws Exception {
+ // START SNIPPET customExceptionPolicyStrategy
+ // configure the error handler to use my policy instead of the
default from Camel
+ errorHandler(deadLetterChannel().exceptionPolicyStrategy(new
MyPolicy()));
+
+ exception(MyPolicyException.class)
+ .maximumRedeliveries(1)
+ .setHeader(MESSAGE_INFO, "Damm my policy exception")
+ .to(errorQueue);
+
+ exception(CamelException.class)
+ .maximumRedeliveries(3)
+ .setHeader(MESSAGE_INFO, "Damm a Camel exception")
+ .to(errorQueue);
+ // END SNIPPET customExceptionPolicyStrategy
+
+ from("direct:a").process(new Processor() {
+ public void process(Exchange exchange) throws Exception {
+ String s = exchange.getIn().getBody(String.class);
+ if ("Hello Camel".equals(s)) {
+ throw new CamelExchangeException("Forced for
testing", exchange);
+ }
+ exchange.getOut().setBody("Hello World");
+ }
+ }).to("mock:result");
+ }
+ };
+ }
+
+}
Added:
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java
URL:
http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java?rev=645063&view=auto
==============================================================================
---
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java
(added)
+++
activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java
Sat Apr 5 03:23:36 2008
@@ -0,0 +1,128 @@
+/**
+ * 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.processor.exceptionpolicy;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.SocketException;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+import org.apache.camel.AlreadyStoppedException;
+import org.apache.camel.CamelExchangeException;
+import org.apache.camel.ExchangeTimedOutException;
+import org.apache.camel.ValidationException;
+import org.apache.camel.model.ExceptionType;
+
+/**
+ * Unit test for DefaultExceptionPolicy
+ */
+public class DefaultExceptionPolicyStrategyTest extends TestCase {
+
+ private DefaultExceptionPolicyStrategy strategy;
+ private HashMap<Class, ExceptionType> policies;
+ private ExceptionType type1;
+ private ExceptionType type2;
+ private ExceptionType type3;
+
+ private void setupPolicies() {
+ strategy = new DefaultExceptionPolicyStrategy();
+ policies = new HashMap<Class, ExceptionType>();
+ type1 = new ExceptionType(CamelExchangeException.class);
+ type2 = new ExceptionType(Exception.class);
+ type3 = new ExceptionType(IOException.class);
+ policies.put(CamelExchangeException.class, type1);
+ policies.put(Exception.class, type2);
+ policies.put(IOException.class, type3);
+ }
+
+ private void setupPoliciesNoTopLevelException() {
+ // without the top level exception that can be used as fallback
+ strategy = new DefaultExceptionPolicyStrategy();
+ policies = new HashMap<Class, ExceptionType>();
+ type1 = new ExceptionType(CamelExchangeException.class);
+ type3 = new ExceptionType(IOException.class);
+ policies.put(CamelExchangeException.class, type1);
+ policies.put(IOException.class, type3);
+ }
+
+ public void testDirectMatch1() {
+ setupPolicies();
+ ExceptionType result = strategy.getExceptionPolicy(policies, null, new
CamelExchangeException("", null));
+ assertEquals(type1, result);
+ }
+
+ public void testDirectMatch2() {
+ setupPolicies();
+ ExceptionType result = strategy.getExceptionPolicy(policies, null, new
Exception(""));
+ assertEquals(type2, result);
+ }
+
+ public void testDirectMatch3() {
+ setupPolicies();
+ ExceptionType result = strategy.getExceptionPolicy(policies, null, new
IOException(""));
+ assertEquals(type3, result);
+ }
+
+ public void testClosetMatch3() {
+ setupPolicies();
+ ExceptionType result = strategy.getExceptionPolicy(policies, null, new
ConnectException(""));
+ assertEquals(type3, result);
+
+ result = strategy.getExceptionPolicy(policies, null, new
SocketException(""));
+ assertEquals(type3, result);
+
+ result = strategy.getExceptionPolicy(policies, null, new
FileNotFoundException());
+ assertEquals(type3, result);
+ }
+
+ public void testClosetMatch2() {
+ setupPolicies();
+ ExceptionType result = strategy.getExceptionPolicy(policies, null, new
ClassCastException(""));
+ assertEquals(type2, result);
+
+ result = strategy.getExceptionPolicy(policies, null, new
NumberFormatException(""));
+ assertEquals(type2, result);
+
+ result = strategy.getExceptionPolicy(policies, null, new
NullPointerException());
+ assertEquals(type2, result);
+ }
+
+ public void testClosetMatch1() {
+ setupPolicies();
+ ExceptionType result = strategy.getExceptionPolicy(policies, null, new
ValidationException(null, ""));
+ assertEquals(type1, result);
+
+ result = strategy.getExceptionPolicy(policies, null, new
ExchangeTimedOutException(null, 0));
+ assertEquals(type1, result);
+ }
+
+ public void testNoMatch1ThenMatchingJustException() {
+ setupPolicies();
+ ExceptionType result = strategy.getExceptionPolicy(policies, null, new
AlreadyStoppedException());
+ assertEquals(type2, result);
+ }
+
+ public void testNoMatch1ThenNull() {
+ setupPoliciesNoTopLevelException();
+ ExceptionType result = strategy.getExceptionPolicy(policies, null, new
AlreadyStoppedException());
+ assertNull("Should not find an exception policy to use", result);
+ }
+
+}