Repository: camel Updated Branches: refs/heads/master 9f66481e0 -> 391e34f7b
CAMEL-9069: Added onExceptionOuccrredProcessor to error handler to allow a processor to be invoked right after an exception was thrown. Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/44e85561 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/44e85561 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/44e85561 Branch: refs/heads/master Commit: 44e85561fea98dc0ead00a033541fadf944d8620 Parents: 9f66481 Author: Claus Ibsen <davscl...@apache.org> Authored: Sun Jan 31 10:31:11 2016 +0100 Committer: Claus Ibsen <davscl...@apache.org> Committed: Sun Jan 31 10:31:11 2016 +0100 ---------------------------------------------------------------------- .../camel/builder/DeadLetterChannelBuilder.java | 3 +- .../builder/DefaultErrorHandlerBuilder.java | 31 +++++++- .../camel/model/OnExceptionDefinition.java | 57 ++++++++++++++- .../camel/processor/DeadLetterChannel.java | 33 +++++---- .../camel/processor/DefaultErrorHandler.java | 35 ++++----- .../camel/processor/LoggingErrorHandler.java | 2 +- .../camel/processor/RedeliveryErrorHandler.java | 59 +++++++++++---- ...ceptionOccurredProcessorOnExceptionTest.java | 77 ++++++++++++++++++++ .../OnExceptionOccurredProcessorTest.java | 75 +++++++++++++++++++ .../blueprint/CamelErrorHandlerFactoryBean.java | 5 ++ .../camel/spring/ErrorHandlerDefinition.java | 2 + .../handler/ErrorHandlerDefinitionParser.java | 7 ++ .../spring/spi/TransactionErrorHandler.java | 6 +- .../spi/TransactionErrorHandlerBuilder.java | 2 +- ...ceptionOccurredProcessorOnExceptionTest.java | 33 +++++++++ .../SpringOnExceptionOccurredProcessorTest.java | 33 +++++++++ ...xceptionOccurredProcessorOnExceptionTest.xml | 47 ++++++++++++ .../OnExceptionOccurredProcessorTest.xml | 44 +++++++++++ ...ceptionOccurredProcessorOnExceptionTest.java | 57 +++++++++++++++ .../OnExceptionOccurredProcessorTest.java | 57 +++++++++++++++ ...xceptionOccurredProcessorOnExceptionTest.xml | 46 ++++++++++++ .../OnExceptionOccurredProcessorTest.xml | 43 +++++++++++ 22 files changed, 701 insertions(+), 53 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java b/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java index 646ed2d..1acd0a8 100644 --- a/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java +++ b/camel-core/src/main/java/org/apache/camel/builder/DeadLetterChannelBuilder.java @@ -55,7 +55,8 @@ public class DeadLetterChannelBuilder extends DefaultErrorHandlerBuilder { DeadLetterChannel answer = new DeadLetterChannel(routeContext.getCamelContext(), processor, getLogger(), getOnRedelivery(), getRedeliveryPolicy(), getExceptionPolicyStrategy(), getFailureProcessor(), getDeadLetterUri(), isDeadLetterHandleNewException(), - isUseOriginalMessage(), getRetryWhilePolicy(routeContext.getCamelContext()), getExecutorService(routeContext.getCamelContext()), getOnPrepareFailure()); + isUseOriginalMessage(), getRetryWhilePolicy(routeContext.getCamelContext()), getExecutorService(routeContext.getCamelContext()), + getOnPrepareFailure(), getOnExceptionOccurred()); // configure error handler before we can use it configure(routeContext, answer); return answer; http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/camel-core/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java b/camel-core/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java index b565bfe..674efae 100644 --- a/camel-core/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java +++ b/camel-core/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java @@ -55,6 +55,7 @@ public class DefaultErrorHandlerBuilder extends ErrorHandlerBuilderSupport { protected String executorServiceRef; protected ScheduledExecutorService executorService; protected Processor onPrepareFailure; + protected Processor onExceptionOccurred; public DefaultErrorHandlerBuilder() { } @@ -62,7 +63,7 @@ public class DefaultErrorHandlerBuilder extends ErrorHandlerBuilderSupport { public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception { DefaultErrorHandler answer = new DefaultErrorHandler(routeContext.getCamelContext(), processor, getLogger(), getOnRedelivery(), getRedeliveryPolicy(), getExceptionPolicyStrategy(), getRetryWhilePolicy(routeContext.getCamelContext()), - getExecutorService(routeContext.getCamelContext()), getOnPrepareFailure()); + getExecutorService(routeContext.getCamelContext()), getOnPrepareFailure(), getOnExceptionOccurred()); // configure error handler before we can use it configure(routeContext, answer); return answer; @@ -106,6 +107,12 @@ public class DefaultErrorHandlerBuilder extends ErrorHandlerBuilderSupport { if (deadLetterUri != null) { other.setDeadLetterUri(deadLetterUri); } + if (onPrepareFailure != null) { + other.setOnPrepareFailure(onPrepareFailure); + } + if (onExceptionOccurred != null) { + other.setOnExceptionOccurred(onExceptionOccurred); + } other.setDeadLetterHandleNewException(deadLetterHandleNewException); other.setUseOriginalMessage(useOriginalMessage); other.setAsyncDelayedRedelivery(asyncDelayedRedelivery); @@ -395,6 +402,20 @@ public class DefaultErrorHandlerBuilder extends ErrorHandlerBuilderSupport { return this; } + /** + * Sets a custom {@link org.apache.camel.Processor} to process the {@link org.apache.camel.Exchange} just after an exception was thrown. + * This allows to execute the processor at the same time the exception was thrown. + * <p/> + * Important: Any exception thrown from this processor will be ignored. + * + * @param processor the processor + * @return the builder + */ + public DefaultErrorHandlerBuilder onExceptionOccurred(Processor processor) { + setOnExceptionOccurred(processor); + return this; + } + // Properties // ------------------------------------------------------------------------- @@ -525,6 +546,14 @@ public class DefaultErrorHandlerBuilder extends ErrorHandlerBuilderSupport { this.onPrepareFailure = onPrepareFailure; } + public Processor getOnExceptionOccurred() { + return onExceptionOccurred; + } + + public void setOnExceptionOccurred(Processor onExceptionOccurred) { + this.onExceptionOccurred = onExceptionOccurred; + } + protected RedeliveryPolicy createRedeliveryPolicy() { RedeliveryPolicy policy = new RedeliveryPolicy(); policy.disableRedelivery(); http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/camel-core/src/main/java/org/apache/camel/model/OnExceptionDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/OnExceptionDefinition.java b/camel-core/src/main/java/org/apache/camel/model/OnExceptionDefinition.java index 9070ae0..f7c06c5 100644 --- a/camel-core/src/main/java/org/apache/camel/model/OnExceptionDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/OnExceptionDefinition.java @@ -72,6 +72,8 @@ public class OnExceptionDefinition extends ProcessorDefinition<OnExceptionDefini private ExpressionSubElementDefinition continued; @XmlAttribute(name = "onRedeliveryRef") private String onRedeliveryRef; + @XmlAttribute(name = "onExceptionOccurredRef") + private String onExceptionbOccurredRef; @XmlAttribute(name = "useOriginalMessage") private Boolean useOriginalMessagePolicy; @XmlElementRef @@ -87,6 +89,8 @@ public class OnExceptionDefinition extends ProcessorDefinition<OnExceptionDefini @XmlTransient private Processor onRedelivery; @XmlTransient + private Processor onExceptionOccurred; + @XmlTransient private Boolean routeScoped; // TODO: in Camel 3.0 the OnExceptionDefinition should not contain state and ErrorHandler processors @XmlTransient @@ -180,6 +184,7 @@ public class OnExceptionDefinition extends ProcessorDefinition<OnExceptionDefini setContinuedFromExpressionType(routeContext); setRetryWhileFromExpressionType(routeContext); setOnRedeliveryFromRedeliveryRef(routeContext); + setOnExceptionOccurredFromOnExceptionOccurredRef(routeContext); // load exception classes if (exceptions != null && !exceptions.isEmpty()) { @@ -247,7 +252,8 @@ public class OnExceptionDefinition extends ProcessorDefinition<OnExceptionDefini if (outputs == null || getOutputs().isEmpty()) { // no outputs so there should be some sort of configuration if (handledPolicy == null && continuedPolicy == null && retryWhilePolicy == null - && redeliveryPolicyType == null && useOriginalMessagePolicy == null && onRedelivery == null) { + && redeliveryPolicyType == null && useOriginalMessagePolicy == null + && onRedelivery == null && onExceptionOccurred == null) { throw new IllegalArgumentException(this + " is not configured."); } } @@ -800,6 +806,30 @@ public class OnExceptionDefinition extends ProcessorDefinition<OnExceptionDefini return this; } + /** + * Sets a processor that should be processed <b>just after</b> an exception occurred. + * Can be used to perform custom logging about the occurred exception at the exact time it happened. + * <p/> + * Important: Any exception thrown from this processor will be ignored. + */ + public OnExceptionDefinition onExceptionOccurred(Processor processor) { + setOnExceptionOccurred(processor); + return this; + } + + /** + * Sets a reference to a processor that should be processed <b>just after</b> an exception occurred. + * Can be used to perform custom logging about the occurred exception at the exact time it happened. + * <p/> + * Important: Any exception thrown from this processor will be ignored. + * + * @param ref reference to the processor + */ + public OnExceptionDefinition onExceptionOccurredRef(String ref) { + setOnExceptionbOccurredRef(ref); + return this; + } + // Properties //------------------------------------------------------------------------- @Override @@ -938,6 +968,22 @@ public class OnExceptionDefinition extends ProcessorDefinition<OnExceptionDefini this.onRedeliveryRef = onRedeliveryRef; } + public Processor getOnExceptionOccurred() { + return onExceptionOccurred; + } + + public void setOnExceptionOccurred(Processor onExceptionOccurred) { + this.onExceptionOccurred = onExceptionOccurred; + } + + public String getOnExceptionbOccurredRef() { + return onExceptionbOccurredRef; + } + + public void setOnExceptionbOccurredRef(String onExceptionbOccurredRef) { + this.onExceptionbOccurredRef = onExceptionbOccurredRef; + } + public Boolean getUseOriginalMessagePolicy() { return useOriginalMessagePolicy; } @@ -1000,4 +1046,13 @@ public class OnExceptionDefinition extends ProcessorDefinition<OnExceptionDefini } } + private void setOnExceptionOccurredFromOnExceptionOccurredRef(RouteContext routeContext) { + // lookup onRedelivery if ref is provided + if (ObjectHelper.isNotEmpty(onExceptionbOccurredRef)) { + // if ref is provided then use mandatory lookup to fail if not found + Processor onExceptionOccurred = CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), onExceptionbOccurredRef, Processor.class); + setOnExceptionOccurred(onExceptionOccurred); + } + } + } http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java b/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java index cc92859..d6e44b6 100644 --- a/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java +++ b/camel-core/src/main/java/org/apache/camel/processor/DeadLetterChannel.java @@ -38,27 +38,28 @@ public class DeadLetterChannel extends RedeliveryErrorHandler { /** * Creates the dead letter channel. * - * @param camelContext the camel context - * @param output outer processor that should use this dead letter channel - * @param logger logger to use for logging failures and redelivery attempts - * @param redeliveryProcessor an optional processor to run before redelivery attempt - * @param redeliveryPolicy policy for redelivery - * @param exceptionPolicyStrategy strategy for onException handling - * @param deadLetter the failure processor to send failed exchanges to - * @param deadLetterUri an optional uri for logging purpose - * @param deadLetterHandleException whether dead letter channel should handle (and ignore) exceptions which may be thrown during sending the message to the dead letter endpoint - * @param useOriginalBodyPolicy should the original IN body be moved to the dead letter queue or the current exchange IN body? - * @param retryWhile retry while - * @param executorService the {@link java.util.concurrent.ScheduledExecutorService} to be used for redelivery thread pool. Can be <tt>null</tt>. - * @param onPrepare a custom {@link org.apache.camel.Processor} to prepare the {@link org.apache.camel.Exchange} before - * handled by the failure processor / dead letter channel. + * @param camelContext the camel context + * @param output outer processor that should use this dead letter channel + * @param logger logger to use for logging failures and redelivery attempts + * @param redeliveryProcessor an optional processor to run before redelivery attempt + * @param redeliveryPolicy policy for redelivery + * @param exceptionPolicyStrategy strategy for onException handling + * @param deadLetter the failure processor to send failed exchanges to + * @param deadLetterUri an optional uri for logging purpose + * @param deadLetterHandleException whether dead letter channel should handle (and ignore) exceptions which may be thrown during sending the message to the dead letter endpoint + * @param useOriginalBodyPolicy should the original IN body be moved to the dead letter queue or the current exchange IN body? + * @param retryWhile retry while + * @param executorService the {@link java.util.concurrent.ScheduledExecutorService} to be used for redelivery thread pool. Can be <tt>null</tt>. + * @param onPrepareProcessor a custom {@link org.apache.camel.Processor} to prepare the {@link org.apache.camel.Exchange} before + * handled by the failure processor / dead letter channel. + * @param onExceptionOccurredProcessor a custom {@link org.apache.camel.Processor} to process the {@link org.apache.camel.Exchange} just after an exception was thrown. */ public DeadLetterChannel(CamelContext camelContext, Processor output, CamelLogger logger, Processor redeliveryProcessor, RedeliveryPolicy redeliveryPolicy, ExceptionPolicyStrategy exceptionPolicyStrategy, Processor deadLetter, String deadLetterUri, boolean deadLetterHandleException, - boolean useOriginalBodyPolicy, Predicate retryWhile, ScheduledExecutorService executorService, Processor onPrepare) { + boolean useOriginalBodyPolicy, Predicate retryWhile, ScheduledExecutorService executorService, Processor onPrepareProcessor, Processor onExceptionOccurredProcessor) { super(camelContext, output, logger, redeliveryProcessor, redeliveryPolicy, deadLetter, deadLetterUri, deadLetterHandleException, - useOriginalBodyPolicy, retryWhile, executorService, onPrepare); + useOriginalBodyPolicy, retryWhile, executorService, onPrepareProcessor, onExceptionOccurredProcessor); setExceptionPolicy(exceptionPolicyStrategy); } http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/camel-core/src/main/java/org/apache/camel/processor/DefaultErrorHandler.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/processor/DefaultErrorHandler.java b/camel-core/src/main/java/org/apache/camel/processor/DefaultErrorHandler.java index 697db20..a8fa1e9 100644 --- a/camel-core/src/main/java/org/apache/camel/processor/DefaultErrorHandler.java +++ b/camel-core/src/main/java/org/apache/camel/processor/DefaultErrorHandler.java @@ -5,9 +5,9 @@ * 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 - * + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> * 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. @@ -28,29 +28,30 @@ import org.apache.camel.util.CamelLogger; /** * Default error handler * - * @version + * @version */ public class DefaultErrorHandler extends RedeliveryErrorHandler { /** * Creates the default error handler. * - * @param camelContext the camel context - * @param output outer processor that should use this default error handler - * @param logger logger to use for logging failures and redelivery attempts - * @param redeliveryProcessor an optional processor to run before redelivery attempt - * @param redeliveryPolicy policy for redelivery - * @param exceptionPolicyStrategy strategy for onException handling - * @param retryWhile retry while - * @param executorService the {@link java.util.concurrent.ScheduledExecutorService} to be used for redelivery thread pool. Can be <tt>null</tt>. - * @param onPrepare a custom {@link org.apache.camel.Processor} to prepare the {@link org.apache.camel.Exchange} before - * handled by the failure processor / dead letter channel. + * @param camelContext the camel context + * @param output outer processor that should use this default error handler + * @param logger logger to use for logging failures and redelivery attempts + * @param redeliveryProcessor an optional processor to run before redelivery attempt + * @param redeliveryPolicy policy for redelivery + * @param exceptionPolicyStrategy strategy for onException handling + * @param retryWhile retry while + * @param executorService the {@link java.util.concurrent.ScheduledExecutorService} to be used for redelivery thread pool. Can be <tt>null</tt>. + * @param onPrepareProcessor a custom {@link org.apache.camel.Processor} to prepare the {@link org.apache.camel.Exchange} before + * handled by the failure processor / dead letter channel. + * @param onExceptionOccurredProcessor a custom {@link org.apache.camel.Processor} to process the {@link org.apache.camel.Exchange} just after an exception was thrown. */ public DefaultErrorHandler(CamelContext camelContext, Processor output, CamelLogger logger, Processor redeliveryProcessor, - RedeliveryPolicy redeliveryPolicy, ExceptionPolicyStrategy exceptionPolicyStrategy, Predicate retryWhile, - ScheduledExecutorService executorService, Processor onPrepare) { + RedeliveryPolicy redeliveryPolicy, ExceptionPolicyStrategy exceptionPolicyStrategy, Predicate retryWhile, + ScheduledExecutorService executorService, Processor onPrepareProcessor, Processor onExceptionOccurredProcessor) { - super(camelContext, output, logger, redeliveryProcessor, redeliveryPolicy, null, null, true, false, retryWhile, executorService, onPrepare); + super(camelContext, output, logger, redeliveryProcessor, redeliveryPolicy, null, null, true, false, retryWhile, executorService, onPrepareProcessor, onExceptionOccurredProcessor); setExceptionPolicy(exceptionPolicyStrategy); } http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/camel-core/src/main/java/org/apache/camel/processor/LoggingErrorHandler.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/processor/LoggingErrorHandler.java b/camel-core/src/main/java/org/apache/camel/processor/LoggingErrorHandler.java index 1f66275..218da95 100644 --- a/camel-core/src/main/java/org/apache/camel/processor/LoggingErrorHandler.java +++ b/camel-core/src/main/java/org/apache/camel/processor/LoggingErrorHandler.java @@ -39,7 +39,7 @@ public class LoggingErrorHandler extends DefaultErrorHandler { */ public LoggingErrorHandler(CamelContext camelContext, Processor output, CamelLogger logger, RedeliveryPolicy redeliveryPolicy, ExceptionPolicyStrategy exceptionPolicyStrategy) { - super(camelContext, output, logger, null, redeliveryPolicy, exceptionPolicyStrategy, null, null, null); + super(camelContext, output, logger, null, redeliveryPolicy, exceptionPolicyStrategy, null, null, null, null); } @Override http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/camel-core/src/main/java/org/apache/camel/processor/RedeliveryErrorHandler.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/processor/RedeliveryErrorHandler.java b/camel-core/src/main/java/org/apache/camel/processor/RedeliveryErrorHandler.java index 8c9a838..9491f3a 100644 --- a/camel-core/src/main/java/org/apache/camel/processor/RedeliveryErrorHandler.java +++ b/camel-core/src/main/java/org/apache/camel/processor/RedeliveryErrorHandler.java @@ -78,7 +78,8 @@ public abstract class RedeliveryErrorHandler extends ErrorHandlerSupport impleme protected volatile boolean preparingShutdown; protected final ExchangeFormatter exchangeFormatter; protected final boolean customExchangeFormatter; - protected final Processor onPrepare; + protected final Processor onPrepareProcessor; + protected final Processor onExceptionProcessor; /** * Contains the current redelivery data @@ -97,6 +98,7 @@ public abstract class RedeliveryErrorHandler extends ErrorHandlerSupport impleme Processor failureProcessor; Processor onRedeliveryProcessor; Processor onPrepareProcessor; + Processor onExceptionProcessor; Predicate handledPredicate; Predicate continuedPredicate; boolean useOriginalInMessage; @@ -108,7 +110,8 @@ public abstract class RedeliveryErrorHandler extends ErrorHandlerSupport impleme this.currentRedeliveryPolicy = redeliveryPolicy; this.deadLetterProcessor = deadLetter; this.onRedeliveryProcessor = redeliveryProcessor; - this.onPrepareProcessor = onPrepare; + this.onPrepareProcessor = RedeliveryErrorHandler.this.onPrepareProcessor; + this.onExceptionProcessor = RedeliveryErrorHandler.this.onExceptionProcessor; this.handledPredicate = getDefaultHandledPredicate(); this.useOriginalInMessage = useOriginalMessagePolicy; this.handleNewException = deadLetterHandleNewException; @@ -202,9 +205,9 @@ public abstract class RedeliveryErrorHandler extends ErrorHandlerSupport impleme } public RedeliveryErrorHandler(CamelContext camelContext, Processor output, CamelLogger logger, - Processor redeliveryProcessor, RedeliveryPolicy redeliveryPolicy, Processor deadLetter, - String deadLetterUri, boolean deadLetterHandleNewException, boolean useOriginalMessagePolicy, - Predicate retryWhile, ScheduledExecutorService executorService, Processor onPrepare) { + Processor redeliveryProcessor, RedeliveryPolicy redeliveryPolicy, Processor deadLetter, + String deadLetterUri, boolean deadLetterHandleNewException, boolean useOriginalMessagePolicy, + Predicate retryWhile, ScheduledExecutorService executorService, Processor onPrepareProcessor, Processor onExceptionProcessor) { ObjectHelper.notNull(camelContext, "CamelContext", this); ObjectHelper.notNull(redeliveryPolicy, "RedeliveryPolicy", this); @@ -221,7 +224,8 @@ public abstract class RedeliveryErrorHandler extends ErrorHandlerSupport impleme this.useOriginalMessagePolicy = useOriginalMessagePolicy; this.retryWhilePolicy = retryWhile; this.executorService = executorService; - this.onPrepare = onPrepare; + this.onPrepareProcessor = onPrepareProcessor; + this.onExceptionProcessor = onExceptionProcessor; if (ObjectHelper.isNotEmpty(redeliveryPolicy.getExchangeFormatterRef())) { ExchangeFormatter formatter = camelContext.getRegistry().lookupByNameAndType(redeliveryPolicy.getExchangeFormatterRef(), ExchangeFormatter.class); @@ -368,6 +372,7 @@ public abstract class RedeliveryErrorHandler extends ErrorHandlerSupport impleme boolean handle = shouldHandleException(exchange); if (handle) { handleException(exchange, data, isDeadLetterChannel()); + onExceptionOccurred(exchange, data); } // compute if we are exhausted, and whether redelivery is allowed @@ -546,6 +551,7 @@ public abstract class RedeliveryErrorHandler extends ErrorHandlerSupport impleme boolean handle = shouldHandleException(exchange); if (handle) { handleException(exchange, data, isDeadLetterChannel()); + onExceptionOccurred(exchange, data); } // compute if we are exhausted or not @@ -805,6 +811,11 @@ public abstract class RedeliveryErrorHandler extends ErrorHandlerSupport impleme if (processor != null) { data.onRedeliveryProcessor = processor; } + // route specific on exception occurred? + processor = exceptionPolicy.getOnExceptionOccurred(); + if (processor != null) { + data.onExceptionProcessor = processor; + } } // only log if not failure handled or not an exhausted unit of work @@ -818,7 +829,29 @@ public abstract class RedeliveryErrorHandler extends ErrorHandlerSupport impleme } /** - * Gives an optional configure redelivery processor a chance to process before the Exchange + * Gives an optional configured OnExceptionOccurred processor a chance to process just after an exception + * was thrown while processing the Exchange. This allows to execute the processor at the same time the exception was thrown. + */ + protected void onExceptionOccurred(Exchange exchange, final RedeliveryData data) { + if (data.onExceptionProcessor == null) { + return; + } + + // run this synchronously as its just a Processor + try { + if (log.isTraceEnabled()) { + log.trace("OnExceptionOccurred processor {} is processing Exchange: {} due exception occurred", data.onExceptionProcessor, exchange); + } + data.onExceptionProcessor.process(exchange); + } catch (Throwable e) { + // we dont not want new exception to override existing, so log it as a WARN + log.warn("Error during processing OnExceptionOccurred. This exception is ignored.", e); + } + log.trace("OnExceptionOccurred processor done"); + } + + /** + * Gives an optional configured redelivery processor a chance to process before the Exchange * will be redelivered. This can be used to alter the Exchange. */ protected void deliverToOnRedeliveryProcessor(final Exchange exchange, final RedeliveryData data) { @@ -897,10 +930,10 @@ public abstract class RedeliveryErrorHandler extends ErrorHandlerSupport impleme MessageHelper.resetStreamCache(exchange.getIn()); // invoke custom on prepare - if (onPrepare != null) { + if (onPrepareProcessor != null) { try { - log.trace("OnPrepare processor {} is processing Exchange: {}", onPrepare, exchange); - onPrepare.process(exchange); + log.trace("OnPrepare processor {} is processing Exchange: {}", onPrepareProcessor, exchange); + onPrepareProcessor.process(exchange); } catch (Exception e) { // a new exception was thrown during prepare exchange.setException(e); @@ -941,10 +974,10 @@ public abstract class RedeliveryErrorHandler extends ErrorHandlerSupport impleme } else { try { // invoke custom on prepare - if (onPrepare != null) { + if (onPrepareProcessor != null) { try { - log.trace("OnPrepare processor {} is processing Exchange: {}", onPrepare, exchange); - onPrepare.process(exchange); + log.trace("OnPrepare processor {} is processing Exchange: {}", onPrepareProcessor, exchange); + onPrepareProcessor.process(exchange); } catch (Exception e) { // a new exception was thrown during prepare exchange.setException(e); http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionOccurredProcessorOnExceptionTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionOccurredProcessorOnExceptionTest.java b/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionOccurredProcessorOnExceptionTest.java new file mode 100644 index 0000000..838f8a3 --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionOccurredProcessorOnExceptionTest.java @@ -0,0 +1,77 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.onexception; + +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.impl.JndiRegistry; + +public class OnExceptionOccurredProcessorOnExceptionTest extends ContextTestSupport { + + @Override + protected JndiRegistry createRegistry() throws Exception { + JndiRegistry jndi = super.createRegistry(); + jndi.bind("myProcessor", new MyProcessor()); + return jndi; + } + + public void testOnExceptionOccurred() throws Exception { + getMockEndpoint("mock:dead").expectedMessageCount(1); + + template.sendBody("direct:start", "Hello World"); + + assertMockEndpointsSatisfied(); + + MyProcessor myProcessor = context.getRegistry().lookupByNameAndType("myProcessor", MyProcessor.class); + // 1 = first time + 3 redelivery attempts + assertEquals(1 + 3, myProcessor.getInvoked()); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + MyProcessor myProcessor = context.getRegistry().lookupByNameAndType("myProcessor", MyProcessor.class); + + errorHandler(deadLetterChannel("mock:dead")); + + onException(Exception.class).maximumRedeliveries(3).redeliveryDelay(0).onExceptionOccurred(myProcessor); + + from("direct:start") + .throwException(new IllegalArgumentException("Forced")); + } + }; + } + + public static class MyProcessor implements Processor { + + private int invoked; + + @Override + public void process(Exchange exchange) throws Exception { + invoked++; + } + + public int getInvoked() { + return invoked; + } + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionOccurredProcessorTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionOccurredProcessorTest.java b/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionOccurredProcessorTest.java new file mode 100644 index 0000000..77d959f --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionOccurredProcessorTest.java @@ -0,0 +1,75 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.onexception; + +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.impl.JndiRegistry; + +public class OnExceptionOccurredProcessorTest extends ContextTestSupport { + + @Override + protected JndiRegistry createRegistry() throws Exception { + JndiRegistry jndi = super.createRegistry(); + jndi.bind("myProcessor", new MyProcessor()); + return jndi; + } + + public void testOnExceptionOccurred() throws Exception { + getMockEndpoint("mock:dead").expectedMessageCount(1); + + template.sendBody("direct:start", "Hello World"); + + assertMockEndpointsSatisfied(); + + MyProcessor myProcessor = context.getRegistry().lookupByNameAndType("myProcessor", MyProcessor.class); + // 1 = first time + 3 redelivery attempts + assertEquals(1 + 3, myProcessor.getInvoked()); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + MyProcessor myProcessor = context.getRegistry().lookupByNameAndType("myProcessor", MyProcessor.class); + + errorHandler(deadLetterChannel("mock:dead").maximumRedeliveries(3).redeliveryDelay(0).onExceptionOccurred(myProcessor)); + + from("direct:start") + .throwException(new IllegalArgumentException("Forced")); + } + }; + } + + public static class MyProcessor implements Processor { + + private int invoked; + + @Override + public void process(Exchange exchange) throws Exception { + invoked++; + } + + public int getInvoked() { + return invoked; + } + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelErrorHandlerFactoryBean.java ---------------------------------------------------------------------- diff --git a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelErrorHandlerFactoryBean.java b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelErrorHandlerFactoryBean.java index 98244a1..2965f93 100644 --- a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelErrorHandlerFactoryBean.java +++ b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelErrorHandlerFactoryBean.java @@ -56,6 +56,8 @@ public class CamelErrorHandlerFactoryBean extends AbstractCamelFactoryBean<Error @XmlAttribute private String onPrepareFailureRef; @XmlAttribute + private String onExceptionOccurredRef; + @XmlAttribute private String retryWhileRef; @XmlAttribute private String executorServiceRef; @@ -92,6 +94,9 @@ public class CamelErrorHandlerFactoryBean extends AbstractCamelFactoryBean<Error if (onPrepareFailureRef != null) { handler.setOnPrepareFailure(lookup(onPrepareFailureRef, Processor.class)); } + if (onExceptionOccurredRef != null) { + handler.setOnExceptionOccurred(lookup(onExceptionOccurredRef, Processor.class)); + } if (retryWhileRef != null) { handler.setRetryWhileRef(retryWhileRef); } http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/components/camel-spring/src/main/java/org/apache/camel/spring/ErrorHandlerDefinition.java ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/ErrorHandlerDefinition.java b/components/camel-spring/src/main/java/org/apache/camel/spring/ErrorHandlerDefinition.java index 43df20b..80fcdb8 100644 --- a/components/camel-spring/src/main/java/org/apache/camel/spring/ErrorHandlerDefinition.java +++ b/components/camel-spring/src/main/java/org/apache/camel/spring/ErrorHandlerDefinition.java @@ -54,6 +54,8 @@ public class ErrorHandlerDefinition extends IdentifiedType { @XmlAttribute private String onRedeliveryRef; @XmlAttribute + private String onExceptionOccurredRef; + @XmlAttribute private String onPrepareFailureRef; @XmlAttribute private String retryWhileRef; http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/components/camel-spring/src/main/java/org/apache/camel/spring/handler/ErrorHandlerDefinitionParser.java ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/handler/ErrorHandlerDefinitionParser.java b/components/camel-spring/src/main/java/org/apache/camel/spring/handler/ErrorHandlerDefinitionParser.java index 65ae81a..0dbc53d 100644 --- a/components/camel-spring/src/main/java/org/apache/camel/spring/handler/ErrorHandlerDefinitionParser.java +++ b/components/camel-spring/src/main/java/org/apache/camel/spring/handler/ErrorHandlerDefinitionParser.java @@ -62,6 +62,7 @@ public class ErrorHandlerDefinitionParser extends BeanDefinitionParser { && !attributeName.equals("onRedeliveryRef") && !attributeName.equals("onRetryWhileRef") && !attributeName.equals("onPrepareFailureRef") + && !attributeName.equals("onExceptionOccurredRef") && !attributeName.equals("redeliveryPolicyRef") && !attributeName.equals("transactionTemplateRef") && !attributeName.equals("transactionManagerRef"); @@ -102,6 +103,7 @@ public class ErrorHandlerDefinitionParser extends BeanDefinitionParser { parserRefAttribute(element, "onRedeliveryRef", "onRedelivery", builder); parserRefAttribute(element, "onRetryWhileRef", "onRetryWhile", builder); parserRefAttribute(element, "onPrepareFailureRef", "onPrepareFailure", builder); + parserRefAttribute(element, "onExceptionOccurredRef", "onExceptionOccurred", builder); parserRefAttribute(element, "redeliveryPolicyRef", "redeliveryPolicy", builder); if (type.equals(ErrorHandlerType.TransactionErrorHandler)) { parserRefAttribute(element, "transactionTemplateRef", "transactionTemplate", builder); @@ -146,6 +148,11 @@ public class ErrorHandlerDefinitionParser extends BeanDefinitionParser { throw new IllegalArgumentException("Attribute onRedeliveryRef is not supported by error handler type: " + type.name() + ", in error handler with id: " + id); } + String onExceptionOccurredRef = element.getAttribute("onExceptionOccurredRef"); + if (ObjectHelper.isNotEmpty(onExceptionOccurredRef) && (type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) { + throw new IllegalArgumentException("Attribute onExceptionOccurredRef is not supported by error handler type: " + + type.name() + ", in error handler with id: " + id); + } String onPrepareFailureRef = element.getAttribute("onPrepareFailureRef"); if (ObjectHelper.isNotEmpty(onPrepareFailureRef) && (type.equals(ErrorHandlerType.TransactionErrorHandler) || type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) { http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandler.java ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandler.java b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandler.java index 3e04802..653ea84 100644 --- a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandler.java +++ b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandler.java @@ -61,13 +61,15 @@ public class TransactionErrorHandler extends RedeliveryErrorHandler { * @param retryWhile retry while * @param executorService the {@link java.util.concurrent.ScheduledExecutorService} to be used for redelivery thread pool. Can be <tt>null</tt>. * @param rollbackLoggingLevel logging level to use for logging transaction rollback occurred + * @param onExceptionOccurredProcessor a custom {@link org.apache.camel.Processor} to process the {@link org.apache.camel.Exchange} just after an exception was thrown. */ public TransactionErrorHandler(CamelContext camelContext, Processor output, CamelLogger logger, Processor redeliveryProcessor, RedeliveryPolicy redeliveryPolicy, ExceptionPolicyStrategy exceptionPolicyStrategy, TransactionTemplate transactionTemplate, Predicate retryWhile, ScheduledExecutorService executorService, - LoggingLevel rollbackLoggingLevel) { + LoggingLevel rollbackLoggingLevel, Processor onExceptionOccurredProcessor) { - super(camelContext, output, logger, redeliveryProcessor, redeliveryPolicy, null, null, false, false, retryWhile, executorService, null); + super(camelContext, output, logger, redeliveryProcessor, redeliveryPolicy, null, null, false, false, retryWhile, + executorService, null, onExceptionOccurredProcessor); setExceptionPolicy(exceptionPolicyStrategy); this.transactionTemplate = transactionTemplate; this.rollbackLoggingLevel = rollbackLoggingLevel; http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandlerBuilder.java ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandlerBuilder.java b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandlerBuilder.java index d3cad1b..2e35574 100644 --- a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandlerBuilder.java +++ b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandlerBuilder.java @@ -107,7 +107,7 @@ public class TransactionErrorHandlerBuilder extends DefaultErrorHandlerBuilder { TransactionErrorHandler answer = new TransactionErrorHandler(routeContext.getCamelContext(), processor, getLogger(), getOnRedelivery(), getRedeliveryPolicy(), getExceptionPolicyStrategy(), transactionTemplate, - getRetryWhilePolicy(routeContext.getCamelContext()), getExecutorService(routeContext.getCamelContext()), getRollbackLoggingLevel()); + getRetryWhilePolicy(routeContext.getCamelContext()), getExecutorService(routeContext.getCamelContext()), getRollbackLoggingLevel(), getOnExceptionOccurred()); // configure error handler before we can use it configure(routeContext, answer); return answer; http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/components/camel-spring/src/test/java/org/apache/camel/spring/processor/onexception/SpringOnExceptionOccurredProcessorOnExceptionTest.java ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/test/java/org/apache/camel/spring/processor/onexception/SpringOnExceptionOccurredProcessorOnExceptionTest.java b/components/camel-spring/src/test/java/org/apache/camel/spring/processor/onexception/SpringOnExceptionOccurredProcessorOnExceptionTest.java new file mode 100644 index 0000000..526b609 --- /dev/null +++ b/components/camel-spring/src/test/java/org/apache/camel/spring/processor/onexception/SpringOnExceptionOccurredProcessorOnExceptionTest.java @@ -0,0 +1,33 @@ +/** + * 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.spring.processor.onexception; + +import org.apache.camel.CamelContext; +import org.apache.camel.processor.onexception.OnExceptionOccurredProcessorOnExceptionTest; + +import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext; + +/** + * @version + */ +public class SpringOnExceptionOccurredProcessorOnExceptionTest extends OnExceptionOccurredProcessorOnExceptionTest { + + protected CamelContext createCamelContext() throws Exception { + return createSpringCamelContext(this, "org/apache/camel/spring/processor/onexception/OnExceptionOccurredProcessorOnExceptionTest.xml"); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/components/camel-spring/src/test/java/org/apache/camel/spring/processor/onexception/SpringOnExceptionOccurredProcessorTest.java ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/test/java/org/apache/camel/spring/processor/onexception/SpringOnExceptionOccurredProcessorTest.java b/components/camel-spring/src/test/java/org/apache/camel/spring/processor/onexception/SpringOnExceptionOccurredProcessorTest.java new file mode 100644 index 0000000..afb67be --- /dev/null +++ b/components/camel-spring/src/test/java/org/apache/camel/spring/processor/onexception/SpringOnExceptionOccurredProcessorTest.java @@ -0,0 +1,33 @@ +/** + * 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.spring.processor.onexception; + +import org.apache.camel.CamelContext; +import org.apache.camel.processor.onexception.OnExceptionOccurredProcessorTest; + +import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext; + +/** + * @version + */ +public class SpringOnExceptionOccurredProcessorTest extends OnExceptionOccurredProcessorTest { + + protected CamelContext createCamelContext() throws Exception { + return createSpringCamelContext(this, "org/apache/camel/spring/processor/onexception/OnExceptionOccurredProcessorTest.xml"); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/onexception/OnExceptionOccurredProcessorOnExceptionTest.xml ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/onexception/OnExceptionOccurredProcessorOnExceptionTest.xml b/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/onexception/OnExceptionOccurredProcessorOnExceptionTest.xml new file mode 100644 index 0000000..442aa11 --- /dev/null +++ b/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/onexception/OnExceptionOccurredProcessorOnExceptionTest.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd + "> + + <bean id="myProcessor" class="org.apache.camel.processor.onexception.OnExceptionOccurredProcessorOnExceptionTest.MyProcessor"/> + + <bean id="forced" class="java.lang.IllegalArgumentException"> + <constructor-arg index="0" value="Forced"/> + </bean> + + <camelContext errorHandlerRef="eh" xmlns="http://camel.apache.org/schema/spring"> + + <errorHandler id="eh" deadLetterUri="mock:dead" type="DeadLetterChannel"/> + + <onException onExceptionOccurredRef="myProcessor"> + <exception>java.lang.Exception</exception> + <redeliveryPolicy maximumRedeliveries="3" redeliveryDelay="0"/> + </onException> + + <route> + <from uri="direct:start"/> + <throwException ref="forced"/> + </route> + + </camelContext> + +</beans> http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/onexception/OnExceptionOccurredProcessorTest.xml ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/onexception/OnExceptionOccurredProcessorTest.xml b/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/onexception/OnExceptionOccurredProcessorTest.xml new file mode 100644 index 0000000..9c032f7 --- /dev/null +++ b/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/onexception/OnExceptionOccurredProcessorTest.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd + "> + + <bean id="myProcessor" class="org.apache.camel.processor.onexception.OnExceptionOccurredProcessorTest.MyProcessor"/> + + <bean id="forced" class="java.lang.IllegalArgumentException"> + <constructor-arg index="0" value="Forced"/> + </bean> + + <camelContext errorHandlerRef="eh" xmlns="http://camel.apache.org/schema/spring"> + + <errorHandler id="eh" deadLetterUri="mock:dead" type="DeadLetterChannel" onExceptionOccurredRef="myProcessor"> + <redeliveryPolicy maximumRedeliveries="3" redeliveryDelay="0"/> + </errorHandler> + + <route> + <from uri="direct:start"/> + <throwException ref="forced"/> + </route> + + </camelContext> + +</beans> http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorOnExceptionTest.java ---------------------------------------------------------------------- diff --git a/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorOnExceptionTest.java b/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorOnExceptionTest.java new file mode 100644 index 0000000..aad66eb --- /dev/null +++ b/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorOnExceptionTest.java @@ -0,0 +1,57 @@ +/** + * 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.test.blueprint; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.junit.Test; + +public class OnExceptionOccurredProcessorOnExceptionTest extends CamelBlueprintTestSupport { + + @Override + protected String getBlueprintDescriptor() { + return "org/apache/camel/test/blueprint/OnExceptionOccurredProcessorOnExceptionTest.xml"; + } + + @Test + public void testOnExceptionOccurred() throws Exception { + getMockEndpoint("mock:dead").expectedMessageCount(1); + + template.sendBody("direct:start", "Hello World"); + + assertMockEndpointsSatisfied(); + + MyProcessor myProcessor = context.getRegistry().lookupByNameAndType("myProcessor", MyProcessor.class); + // 1 = first time + 3 redelivery attempts + assertEquals(1 + 3, myProcessor.getInvoked()); + } + + public static class MyProcessor implements Processor { + + private int invoked; + + @Override + public void process(Exchange exchange) throws Exception { + invoked++; + } + + public int getInvoked() { + return invoked; + } + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorTest.java ---------------------------------------------------------------------- diff --git a/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorTest.java b/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorTest.java new file mode 100644 index 0000000..57b8621 --- /dev/null +++ b/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorTest.java @@ -0,0 +1,57 @@ +/** + * 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.test.blueprint; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.junit.Test; + +public class OnExceptionOccurredProcessorTest extends CamelBlueprintTestSupport { + + @Override + protected String getBlueprintDescriptor() { + return "org/apache/camel/test/blueprint/OnExceptionOccurredProcessorTest.xml"; + } + + @Test + public void testOnExceptionOccurred() throws Exception { + getMockEndpoint("mock:dead").expectedMessageCount(1); + + template.sendBody("direct:start", "Hello World"); + + assertMockEndpointsSatisfied(); + + MyProcessor myProcessor = context.getRegistry().lookupByNameAndType("myProcessor", MyProcessor.class); + // 1 = first time + 3 redelivery attempts + assertEquals(1 + 3, myProcessor.getInvoked()); + } + + public static class MyProcessor implements Processor { + + private int invoked; + + @Override + public void process(Exchange exchange) throws Exception { + invoked++; + } + + public int getInvoked() { + return invoked; + } + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorOnExceptionTest.xml ---------------------------------------------------------------------- diff --git a/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorOnExceptionTest.xml b/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorOnExceptionTest.xml new file mode 100644 index 0000000..39db3a0 --- /dev/null +++ b/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorOnExceptionTest.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> + + <bean id="myProcessor" class="org.apache.camel.test.blueprint.OnExceptionOccurredProcessorOnExceptionTest.MyProcessor"/> + + <bean id="forced" class="java.lang.IllegalArgumentException"> + <argument index="0" value="Forced"/> + </bean> + + <camelContext errorHandlerRef="eh" xmlns="http://camel.apache.org/schema/blueprint"> + + <errorHandler id="eh" deadLetterUri="mock:dead" type="DeadLetterChannel"/> + + <onException onExceptionOccurredRef="myProcessor"> + <exception>java.lang.Exception</exception> + <redeliveryPolicy maximumRedeliveries="3" redeliveryDelay="0"/> + </onException> + + <route> + <from uri="direct:start"/> + <throwException ref="forced"/> + </route> + + </camelContext> + +</blueprint> + http://git-wip-us.apache.org/repos/asf/camel/blob/44e85561/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorTest.xml ---------------------------------------------------------------------- diff --git a/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorTest.xml b/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorTest.xml new file mode 100644 index 0000000..0285024 --- /dev/null +++ b/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/OnExceptionOccurredProcessorTest.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> + + <bean id="myProcessor" class="org.apache.camel.test.blueprint.OnExceptionOccurredProcessorTest.MyProcessor"/> + + <bean id="forced" class="java.lang.IllegalArgumentException"> + <argument index="0" value="Forced"/> + </bean> + + <camelContext errorHandlerRef="eh" xmlns="http://camel.apache.org/schema/blueprint"> + + <errorHandler id="eh" deadLetterUri="mock:dead" type="DeadLetterChannel" onExceptionOccurredRef="myProcessor"> + <redeliveryPolicy maximumRedeliveries="3" redeliveryDelay="0"/> + </errorHandler> + + <route> + <from uri="direct:start"/> + <throwException ref="forced"/> + </route> + + </camelContext> + +</blueprint> +