You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by gn...@apache.org on 2019/05/28 21:56:53 UTC

[camel] branch master updated (36cdd36 -> bfe9336)

This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git.


    from 36cdd36  [CAMEL-13593]avoid “expected resource not found” warnings when using camel-mail in OSGi
     new 552ee0c  [CAMEL-13564] Split exception/error handling model from runtime
     new 0b0663e  [CAMEL-13564] Move error handler processors to camel-base
     new eccc13c  [CAMEL-13564] Move more methods to ErrorHandlerReifier
     new c129943  [CAMEL-13564] Remove redundant error handler configuration
     new 8f5f59f  Use custom ports for management tests
     new 63634ae  [CAMEL-13564] Move state from ErrorHandlerBuilder to RouteContext
     new bfe9336  [CAMEL-13564] Move DefaultChannel to camel-base

The 7 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 components/camel-blueprint/pom.xml                 |   4 +
 .../blueprint/CamelErrorHandlerFactoryBean.java    |   2 +-
 .../transaction/JtaTransactionErrorHandler.java    |   2 +-
 .../cdi/transaction/JtaTransactionPolicy.java      |  12 +-
 .../cdi/transaction/TransactionErrorHandler.java   |   2 +-
 .../camel/spring/spi/SpringTransactionPolicy.java  |  15 +-
 .../camel/spring/spi/TransactionErrorHandler.java  |   2 +-
 .../spring/spi/TransactionErrorHandlerBuilder.java |   5 +
 .../spring/spi/TransactionErrorHandlerReifier.java |  89 +++++
 .../src/main/java/org/apache/camel/Channel.java    |  45 +--
 .../java/org/apache/camel/spi/RouteContext.java    |  24 ++
 .../camel/impl/engine/DefaultRouteContext.java     |  22 ++
 .../camel/processor/channel/DefaultChannel.java    | 136 +++-----
 .../processor/errorhandler/DeadLetterChannel.java  |   1 -
 .../errorhandler/DefaultErrorHandler.java          |   1 -
 .../DefaultExceptionPolicyStrategy.java            |  89 +++--
 .../errorhandler/ErrorHandlerSupport.java          |  93 ++++++
 .../processor/errorhandler/ExceptionPolicy.java    | 261 +++++++++++++++
 .../errorhandler}/ExceptionPolicyKey.java          |  12 +-
 .../errorhandler}/ExceptionPolicyStrategy.java     |  14 +-
 .../errorhandler/RedeliveryErrorHandler.java       |  29 +-
 .../processor/errorhandler/RedeliveryPolicy.java   |   0
 .../camel/processor/errorhandler}/package.html     |   0
 .../camel/builder/DefaultErrorHandlerBuilder.java  |   8 +
 .../apache/camel/builder/ErrorHandlerBuilder.java  |  46 ---
 .../camel/builder/ErrorHandlerBuilderRef.java      | 138 +-------
 .../camel/builder/ErrorHandlerBuilderSupport.java  | 112 ++++---
 .../camel/impl/AbstractModelCamelContext.java      |   5 -
 .../java/org/apache/camel/model/ModelChannel.java  |  56 ----
 .../org/apache/camel/model/RouteDefinition.java    |   3 +-
 .../errorhandler/ErrorHandlerSupport.java          | 137 --------
 .../apache/camel/reifier/DynamicRouterReifier.java |   6 +-
 .../apache/camel/reifier/ErrorHandlerReifier.java  | 152 ---------
 .../apache/camel/reifier/OnExceptionReifier.java   |   2 +-
 .../org/apache/camel/reifier/ProcessorReifier.java |  72 ++--
 .../apache/camel/reifier/RoutingSlipReifier.java   |   3 +-
 .../errorhandler/DeadLetterChannelReifier.java     |  48 +++
 .../errorhandler/DefaultErrorHandlerReifier.java   |  63 ++++
 .../errorhandler/ErrorHandlerRefReifier.java       |  19 ++
 .../reifier/errorhandler/ErrorHandlerReifier.java  | 361 +++++++++++++++++++++
 .../errorhandler/NoErrorHandlerReifier.java        |  41 +++
 .../camel/builder/ErrorHandlerBuilderRefTest.java  |  90 -----
 .../ValidatorEndpointClearCachedSchemaTest.java    |   5 +
 .../RandomLoadBalanceJavaDSLBuilderTest.java       |   2 +-
 .../errorhandler/ErrorHandlerSupportTest.java      |  13 +-
 .../CustomExceptionPolicyStrategyTest.java         |  13 +-
 .../DefaultExceptionPolicyStrategyTest.java        |  71 ++--
 .../DefaultManagementObjectNameStrategy.java       |   7 +-
 .../camel/management/ManagedComponentTest.java     |   3 +-
 .../camel/management/ManagementTestSupport.java    |  19 ++
 .../camel/management/util/AvailablePortFinder.java | 167 ++++++++++
 51 files changed, 1558 insertions(+), 964 deletions(-)
 create mode 100644 components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandlerReifier.java
 rename core/{camel-core => camel-base}/src/main/java/org/apache/camel/processor/channel/DefaultChannel.java (73%)
 rename core/{camel-core => camel-base}/src/main/java/org/apache/camel/processor/errorhandler/DeadLetterChannel.java (98%)
 rename core/{camel-core => camel-base}/src/main/java/org/apache/camel/processor/errorhandler/DefaultErrorHandler.java (97%)
 rename core/{camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy => camel-base/src/main/java/org/apache/camel/processor/errorhandler}/DefaultExceptionPolicyStrategy.java (70%)
 create mode 100644 core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupport.java
 create mode 100644 core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/ExceptionPolicy.java
 rename core/{camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy => camel-base/src/main/java/org/apache/camel/processor/errorhandler}/ExceptionPolicyKey.java (90%)
 rename core/{camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy => camel-base/src/main/java/org/apache/camel/processor/errorhandler}/ExceptionPolicyStrategy.java (65%)
 rename core/{camel-core => camel-base}/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryErrorHandler.java (97%)
 rename core/{camel-core => camel-base}/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryPolicy.java (100%)
 rename core/{camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy => camel-base/src/main/java/org/apache/camel/processor/errorhandler}/package.html (100%)
 delete mode 100644 core/camel-core/src/main/java/org/apache/camel/model/ModelChannel.java
 delete mode 100644 core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupport.java
 delete mode 100644 core/camel-core/src/main/java/org/apache/camel/reifier/ErrorHandlerReifier.java
 create mode 100644 core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/DeadLetterChannelReifier.java
 create mode 100644 core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/DefaultErrorHandlerReifier.java
 create mode 100644 core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerRefReifier.java
 create mode 100644 core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java
 create mode 100644 core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/NoErrorHandlerReifier.java
 delete mode 100644 core/camel-core/src/test/java/org/apache/camel/builder/ErrorHandlerBuilderRefTest.java
 create mode 100644 core/camel-management-impl/src/test/java/org/apache/camel/management/util/AvailablePortFinder.java


[camel] 03/07: [CAMEL-13564] Move more methods to ErrorHandlerReifier

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit eccc13cf676fe823522b7590087d3eae648873d1
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Mon May 27 22:40:31 2019 +0200

    [CAMEL-13564] Move more methods to ErrorHandlerReifier
---
 .../cdi/transaction/JtaTransactionPolicy.java      |   4 +-
 .../camel/spring/spi/SpringTransactionPolicy.java  |   4 +-
 .../camel/builder/ErrorHandlerBuilderRef.java      | 101 +--------------------
 .../org/apache/camel/model/RouteDefinition.java    |   3 +-
 .../reifier/errorhandler/ErrorHandlerReifier.java  |  99 ++++++++++++++++++++
 .../DefaultManagementObjectNameStrategy.java       |   7 +-
 6 files changed, 110 insertions(+), 108 deletions(-)

diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java
index d2dd5ebe..e0e6c46 100644
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java
@@ -87,9 +87,9 @@ public abstract class JtaTransactionPolicy implements TransactedPolicy {
             // only lookup if there was explicit an error handler builder configured
             // otherwise its just the "default" that has not explicit been configured
             // and if so then we can safely replace that with our transacted error handler
-            if (ErrorHandlerBuilderRef.isErrorHandlerFactoryConfigured(ref)) {
+            if (ErrorHandlerReifier.isErrorHandlerFactoryConfigured(ref)) {
                 LOG.debug("Looking up ErrorHandlerBuilder with ref: {}", ref);
-                builder = (ErrorHandlerBuilder) ErrorHandlerBuilderRef.lookupErrorHandlerFactory(routeContext, ref);
+                builder = (ErrorHandlerBuilder) ErrorHandlerReifier.lookupErrorHandlerFactory(routeContext, ref);
             }
         }
 
diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java
index a67b4f3..a35f9b2 100644
--- a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java
+++ b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java
@@ -80,9 +80,9 @@ public class SpringTransactionPolicy implements TransactedPolicy {
             // only lookup if there was explicit an error handler builder configured
             // otherwise its just the "default" that has not explicit been configured
             // and if so then we can safely replace that with our transacted error handler
-            if (ErrorHandlerBuilderRef.isErrorHandlerFactoryConfigured(ref)) {
+            if (ErrorHandlerReifier.isErrorHandlerFactoryConfigured(ref)) {
                 LOG.debug("Looking up ErrorHandlerBuilder with ref: {}", ref);
-                builder = (ErrorHandlerBuilder)ErrorHandlerBuilderRef.lookupErrorHandlerFactory(routeContext, ref);
+                builder = (ErrorHandlerBuilder) ErrorHandlerReifier.lookupErrorHandlerFactory(routeContext, ref);
             }
         }
 
diff --git a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java
index 27e4c42..2d854e3 100644
--- a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java
+++ b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java
@@ -20,12 +20,9 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.camel.CamelContext;
 import org.apache.camel.ErrorHandlerFactory;
-import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.Processor;
 import org.apache.camel.model.OnExceptionDefinition;
-import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.util.ObjectHelper;
@@ -34,7 +31,6 @@ import org.apache.camel.util.ObjectHelper;
  * Represents a proxy to an error handler builder which is resolved by named reference
  */
 public class ErrorHandlerBuilderRef extends ErrorHandlerBuilderSupport {
-    public static final String DEFAULT_ERROR_HANDLER_BUILDER = "CamelDefaultErrorHandlerBuilder";
     private final String ref;
     private final Map<RouteContext, ErrorHandlerBuilder> handlers = new HashMap<>();
     private boolean supportTransacted;
@@ -88,107 +84,12 @@ public class ErrorHandlerBuilderRef extends ErrorHandlerBuilderSupport {
         other.supportTransacted = supportTransacted;
     }
 
-    /**
-     * Lookup the error handler by the given ref
-     *
-     * @param routeContext the route context
-     * @param ref          reference id for the error handler
-     * @return the error handler
-     */
-    public static ErrorHandlerFactory lookupErrorHandlerFactory(RouteContext routeContext, String ref) {
-        return lookupErrorHandlerFactory(routeContext, ref, true);
-    }
-
-    /**
-     * Lookup the error handler by the given ref
-     *
-     * @param routeContext the route context
-     * @param ref          reference id for the error handler
-     * @param mandatory    whether the error handler must exists, if not a {@link org.apache.camel.NoSuchBeanException} is thrown
-     * @return the error handler
-     */
-    public static ErrorHandlerFactory lookupErrorHandlerFactory(RouteContext routeContext, String ref, boolean mandatory) {
-        ErrorHandlerFactory answer;
-
-        // if the ref is the default then we do not have any explicit error handler configured
-        // if that is the case then use error handlers configured on the route, as for instance
-        // the transacted error handler could have been configured on the route so we should use that one
-        if (!isErrorHandlerFactoryConfigured(ref)) {
-            // see if there has been configured a route builder on the route
-            RouteDefinition route = (RouteDefinition) routeContext.getRoute();
-            answer = route.getErrorHandlerFactory();
-            if (answer == null && route.getErrorHandlerRef() != null) {
-                answer = routeContext.lookup(route.getErrorHandlerRef(), ErrorHandlerBuilder.class);
-            }
-            if (answer == null) {
-                // fallback to the default error handler if none configured on the route
-                answer = new DefaultErrorHandlerBuilder();
-            }
-            // check if its also a ref with no error handler configuration like me
-            if (answer instanceof ErrorHandlerBuilderRef) {
-                ErrorHandlerBuilderRef other = (ErrorHandlerBuilderRef) answer;
-                String otherRef = other.getRef();
-                if (!isErrorHandlerFactoryConfigured(otherRef)) {
-                    // the other has also no explicit error handler configured then fallback to the handler
-                    // configured on the parent camel context
-                    answer = lookupErrorHandlerFactory(routeContext.getCamelContext());
-                }
-                if (answer == null) {
-                    // the other has also no explicit error handler configured then fallback to the default error handler
-                    // otherwise we could recursive loop forever (triggered by createErrorHandler method)
-                    answer = new DefaultErrorHandlerBuilder();
-                }
-                // inherit the error handlers from the other as they are to be shared
-                // this is needed by camel-spring when none error handler has been explicit configured
-                ((ErrorHandlerBuilder)answer).setErrorHandlers(routeContext, other.getErrorHandlers(routeContext));
-            }
-        } else {
-            // use specific configured error handler
-            if (mandatory) {
-                answer = routeContext.mandatoryLookup(ref, ErrorHandlerBuilder.class);
-            } else {
-                answer = routeContext.lookup(ref, ErrorHandlerBuilder.class);
-            }
-        }
-
-        return answer;
-    }
-
-    protected static ErrorHandlerFactory lookupErrorHandlerFactory(CamelContext camelContext) {
-        ErrorHandlerFactory answer = camelContext.adapt(ExtendedCamelContext.class).getErrorHandlerFactory();
-        if (answer instanceof ErrorHandlerBuilderRef) {
-            ErrorHandlerBuilderRef other = (ErrorHandlerBuilderRef) answer;
-            String otherRef = other.getRef();
-            if (isErrorHandlerFactoryConfigured(otherRef)) {
-                answer = camelContext.getRegistry().lookupByNameAndType(otherRef, ErrorHandlerBuilder.class);
-                if (answer == null) {
-                    throw new IllegalArgumentException("ErrorHandlerBuilder with id " + otherRef + " not found in registry.");
-                }
-            }
-        }
-
-        return answer;
-    }
-
-    /**
-     * Returns whether a specific error handler builder has been configured or not.
-     * <p/>
-     * Can be used to test if none has been configured and then install a custom error handler builder
-     * replacing the default error handler (that would have been used as fallback otherwise).
-     * <br/>
-     * This is for instance used by the transacted policy to setup a TransactedErrorHandlerBuilder
-     * in camel-spring.
-     */
-    public static boolean isErrorHandlerFactoryConfigured(String ref) {
-        return !DEFAULT_ERROR_HANDLER_BUILDER.equals(ref);
-    }
-
     public String getRef() {
         return ref;
     }
 
     private ErrorHandlerBuilder createErrorHandler(RouteContext routeContext) {
-        ErrorHandlerBuilder handler = (ErrorHandlerBuilder) lookupErrorHandlerFactory(routeContext, getRef());
+        ErrorHandlerBuilder handler = (ErrorHandlerBuilder) ErrorHandlerReifier.lookupErrorHandlerFactory(routeContext, getRef());
         ObjectHelper.notNull(handler, "error handler '" + ref + "'");
 
         // configure if the handler support transacted
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java b/core/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java
index dcc96ac..c1b4305 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java
@@ -36,6 +36,7 @@ import org.apache.camel.ShutdownRunningTask;
 import org.apache.camel.builder.ErrorHandlerBuilderRef;
 import org.apache.camel.model.rest.RestBindingDefinition;
 import org.apache.camel.model.rest.RestDefinition;
+import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
 import org.apache.camel.spi.AsEndpointUri;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.RoutePolicy;
@@ -909,7 +910,7 @@ public class RouteDefinition extends ProcessorDefinition<RouteDefinition> {
         }
 
         // return a reference to the default error handler
-        return new ErrorHandlerBuilderRef(ErrorHandlerBuilderRef.DEFAULT_ERROR_HANDLER_BUILDER);
+        return new ErrorHandlerBuilderRef(ErrorHandlerReifier.DEFAULT_ERROR_HANDLER_BUILDER);
     }
 
     @XmlTransient
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java
index ca15e64..a7649ca 100644
--- a/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java
@@ -23,15 +23,18 @@ import java.util.function.Function;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ErrorHandlerFactory;
+import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.Processor;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.builder.DeadLetterChannelBuilder;
 import org.apache.camel.builder.DefaultErrorHandlerBuilder;
+import org.apache.camel.builder.ErrorHandlerBuilder;
 import org.apache.camel.builder.ErrorHandlerBuilderRef;
 import org.apache.camel.builder.ErrorHandlerBuilderSupport;
 import org.apache.camel.builder.NoErrorHandlerBuilder;
 import org.apache.camel.model.OnExceptionDefinition;
 import org.apache.camel.model.RedeliveryPolicyDefinition;
+import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.processor.ErrorHandler;
 import org.apache.camel.processor.errorhandler.ExceptionPolicy;
 import org.apache.camel.processor.errorhandler.ExceptionPolicy.RedeliveryOption;
@@ -44,6 +47,7 @@ import org.apache.camel.util.ObjectHelper;
 
 public abstract class ErrorHandlerReifier<T extends ErrorHandlerBuilderSupport> {
 
+    public static final String DEFAULT_ERROR_HANDLER_BUILDER = "CamelDefaultErrorHandlerBuilder";
     private static final Map<Class<?>, Function<ErrorHandlerFactory, ErrorHandlerReifier<? extends ErrorHandlerFactory>>> ERROR_HANDLERS;
     static {
         Map<Class<?>, Function<ErrorHandlerFactory, ErrorHandlerReifier<? extends ErrorHandlerFactory>>> map = new HashMap<>();
@@ -138,6 +142,101 @@ public abstract class ErrorHandlerReifier<T extends ErrorHandlerBuilderSupport>
     }
 
     /**
+     * Lookup the error handler by the given ref
+     *
+     * @param routeContext the route context
+     * @param ref          reference id for the error handler
+     * @return the error handler
+     */
+    public static ErrorHandlerFactory lookupErrorHandlerFactory(RouteContext routeContext, String ref) {
+        return lookupErrorHandlerFactory(routeContext, ref, true);
+    }
+
+    /**
+     * Lookup the error handler by the given ref
+     *
+     * @param routeContext the route context
+     * @param ref          reference id for the error handler
+     * @param mandatory    whether the error handler must exists, if not a {@link org.apache.camel.NoSuchBeanException} is thrown
+     * @return the error handler
+     */
+    public static ErrorHandlerFactory lookupErrorHandlerFactory(RouteContext routeContext, String ref, boolean mandatory) {
+        ErrorHandlerFactory answer;
+
+        // if the ref is the default then we do not have any explicit error handler configured
+        // if that is the case then use error handlers configured on the route, as for instance
+        // the transacted error handler could have been configured on the route so we should use that one
+        if (!isErrorHandlerFactoryConfigured(ref)) {
+            // see if there has been configured a route builder on the route
+            RouteDefinition route = (RouteDefinition) routeContext.getRoute();
+            answer = route.getErrorHandlerFactory();
+            if (answer == null && route.getErrorHandlerRef() != null) {
+                answer = routeContext.lookup(route.getErrorHandlerRef(), ErrorHandlerBuilder.class);
+            }
+            if (answer == null) {
+                // fallback to the default error handler if none configured on the route
+                answer = new DefaultErrorHandlerBuilder();
+            }
+            // check if its also a ref with no error handler configuration like me
+            if (answer instanceof ErrorHandlerBuilderRef) {
+                ErrorHandlerBuilderRef other = (ErrorHandlerBuilderRef) answer;
+                String otherRef = other.getRef();
+                if (!isErrorHandlerFactoryConfigured(otherRef)) {
+                    // the other has also no explicit error handler configured then fallback to the handler
+                    // configured on the parent camel context
+                    answer = lookupErrorHandlerFactory(routeContext.getCamelContext());
+                }
+                if (answer == null) {
+                    // the other has also no explicit error handler configured then fallback to the default error handler
+                    // otherwise we could recursive loop forever (triggered by createErrorHandler method)
+                    answer = new DefaultErrorHandlerBuilder();
+                }
+                // inherit the error handlers from the other as they are to be shared
+                // this is needed by camel-spring when none error handler has been explicit configured
+                ((ErrorHandlerBuilderSupport) answer).setErrorHandlers(routeContext, other.getErrorHandlers(routeContext));
+            }
+        } else {
+            // use specific configured error handler
+            if (mandatory) {
+                answer = routeContext.mandatoryLookup(ref, ErrorHandlerBuilder.class);
+            } else {
+                answer = routeContext.lookup(ref, ErrorHandlerBuilder.class);
+            }
+        }
+
+        return answer;
+    }
+
+    protected static ErrorHandlerFactory lookupErrorHandlerFactory(CamelContext camelContext) {
+        ErrorHandlerFactory answer = camelContext.adapt(ExtendedCamelContext.class).getErrorHandlerFactory();
+        if (answer instanceof ErrorHandlerBuilderRef) {
+            ErrorHandlerBuilderRef other = (ErrorHandlerBuilderRef) answer;
+            String otherRef = other.getRef();
+            if (isErrorHandlerFactoryConfigured(otherRef)) {
+                answer = camelContext.getRegistry().lookupByNameAndType(otherRef, ErrorHandlerBuilder.class);
+                if (answer == null) {
+                    throw new IllegalArgumentException("ErrorHandlerBuilder with id " + otherRef + " not found in registry.");
+                }
+            }
+        }
+
+        return answer;
+    }
+
+    /**
+     * Returns whether a specific error handler builder has been configured or not.
+     * <p/>
+     * Can be used to test if none has been configured and then install a custom error handler builder
+     * replacing the default error handler (that would have been used as fallback otherwise).
+     * <br/>
+     * This is for instance used by the transacted policy to setup a TransactedErrorHandlerBuilder
+     * in camel-spring.
+     */
+    public static boolean isErrorHandlerFactoryConfigured(String ref) {
+        return !DEFAULT_ERROR_HANDLER_BUILDER.equals(ref);
+    }
+
+    /**
      * Creates the error handler
      *
      * @param routeContext the route context
diff --git a/core/camel-management-impl/src/main/java/org/apache/camel/management/DefaultManagementObjectNameStrategy.java b/core/camel-management-impl/src/main/java/org/apache/camel/management/DefaultManagementObjectNameStrategy.java
index ad49c11..8122534 100644
--- a/core/camel-management-impl/src/main/java/org/apache/camel/management/DefaultManagementObjectNameStrategy.java
+++ b/core/camel-management-impl/src/main/java/org/apache/camel/management/DefaultManagementObjectNameStrategy.java
@@ -54,6 +54,7 @@ import org.apache.camel.management.mbean.ManagedRouteController;
 import org.apache.camel.management.mbean.ManagedService;
 import org.apache.camel.management.mbean.ManagedStep;
 import org.apache.camel.management.mbean.ManagedThreadPool;
+import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
 import org.apache.camel.spi.DataFormat;
 import org.apache.camel.spi.EventNotifier;
 import org.apache.camel.spi.ManagementObjectNameStrategy;
@@ -300,7 +301,7 @@ public class DefaultManagementObjectNameStrategy implements ManagementObjectName
 
             // it has not then its an indirection and we should do some work to lookup the real builder
             ref = builderRef.getRef();
-            ErrorHandlerFactory refBuilder = ErrorHandlerBuilderRef.lookupErrorHandlerFactory(routeContext, builderRef.getRef(), false);
+            ErrorHandlerFactory refBuilder = ErrorHandlerReifier.lookupErrorHandlerFactory(routeContext, builderRef.getRef(), false);
             if (refBuilder != null) {
                 builder = refBuilder;
             }
@@ -311,8 +312,8 @@ public class DefaultManagementObjectNameStrategy implements ManagementObjectName
             if (builder instanceof ErrorHandlerBuilderRef) {
                 builderRef = (ErrorHandlerBuilderRef) builder;
                 // does it refer to a non default error handler then do a 2nd lookup
-                if (!builderRef.getRef().equals(ErrorHandlerBuilderRef.DEFAULT_ERROR_HANDLER_BUILDER)) {
-                    refBuilder = ErrorHandlerBuilderRef.lookupErrorHandlerFactory(routeContext, builderRef.getRef(), false);
+                if (!builderRef.getRef().equals(ErrorHandlerReifier.DEFAULT_ERROR_HANDLER_BUILDER)) {
+                    refBuilder = ErrorHandlerReifier.lookupErrorHandlerFactory(routeContext, builderRef.getRef(), false);
                     if (refBuilder != null) {
                         ref = builderRef.getRef();
                         builder = refBuilder;


[camel] 02/07: [CAMEL-13564] Move error handler processors to camel-base

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 0b0663e95d6419ffce34aeebb005c174bc0c1466
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Fri May 24 18:05:43 2019 +0200

    [CAMEL-13564] Move error handler processors to camel-base
---
 .../transaction/JtaTransactionErrorHandler.java    |   2 +-
 .../cdi/transaction/TransactionErrorHandler.java   |   2 +-
 .../camel/spring/spi/TransactionErrorHandler.java  |   2 +-
 .../processor/errorhandler/DeadLetterChannel.java  |   1 -
 .../errorhandler/DefaultErrorHandler.java          |   1 -
 .../DefaultExceptionPolicyStrategy.java            |  80 +++----
 .../errorhandler/ErrorHandlerSupport.java          |   9 +-
 .../processor/errorhandler/ExceptionPolicy.java    | 261 +++++++++++++++++++++
 .../errorhandler}/ExceptionPolicyKey.java          |   4 +-
 .../errorhandler}/ExceptionPolicyStrategy.java     |  13 +-
 .../errorhandler/RedeliveryErrorHandler.java       |   1 -
 .../processor/errorhandler/RedeliveryPolicy.java   |   0
 .../camel/processor/errorhandler}/package.html     |   0
 .../apache/camel/builder/ErrorHandlerBuilder.java  |   2 +-
 .../camel/builder/ErrorHandlerBuilderSupport.java  |  15 +-
 .../processor/exceptionpolicy/ExceptionPolicy.java |  85 -------
 .../apache/camel/reifier/DynamicRouterReifier.java |   2 +-
 .../apache/camel/reifier/OnExceptionReifier.java   |   1 -
 .../errorhandler/DefaultErrorHandlerReifier.java   |   6 -
 .../reifier/errorhandler/ErrorHandlerReifier.java  | 109 +++++----
 .../CustomExceptionPolicyStrategyTest.java         |  12 +-
 .../DefaultExceptionPolicyStrategyTest.java        |  63 +++--
 22 files changed, 427 insertions(+), 244 deletions(-)

diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionErrorHandler.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionErrorHandler.java
index 915b7b0..19e9f9a 100644
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionErrorHandler.java
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionErrorHandler.java
@@ -24,7 +24,7 @@ import org.apache.camel.Predicate;
 import org.apache.camel.Processor;
 import org.apache.camel.processor.errorhandler.RedeliveryErrorHandler;
 import org.apache.camel.processor.errorhandler.RedeliveryPolicy;
-import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
+import org.apache.camel.processor.errorhandler.ExceptionPolicyStrategy;
 import org.apache.camel.spi.CamelLogger;
 
 /**
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/TransactionErrorHandler.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/TransactionErrorHandler.java
index c8f43ae..deb42af 100644
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/TransactionErrorHandler.java
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/TransactionErrorHandler.java
@@ -32,7 +32,7 @@ import org.apache.camel.Navigate;
 import org.apache.camel.Processor;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.processor.errorhandler.ErrorHandlerSupport;
-import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
+import org.apache.camel.processor.errorhandler.ExceptionPolicyStrategy;
 import org.apache.camel.spi.ShutdownPrepared;
 import org.apache.camel.support.AsyncCallbackToCompletableFutureAdapter;
 import org.apache.camel.support.ExchangeHelper;
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 c6be3d7..7a06af2 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
@@ -27,7 +27,7 @@ import org.apache.camel.Processor;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.processor.errorhandler.RedeliveryErrorHandler;
 import org.apache.camel.processor.errorhandler.RedeliveryPolicy;
-import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
+import org.apache.camel.processor.errorhandler.ExceptionPolicyStrategy;
 import org.apache.camel.spi.CamelLogger;
 import org.apache.camel.support.AsyncProcessorSupport;
 import org.apache.camel.support.ExchangeHelper;
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/DeadLetterChannel.java b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/DeadLetterChannel.java
similarity index 98%
rename from core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/DeadLetterChannel.java
rename to core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/DeadLetterChannel.java
index b741bc3..d7b9f00 100644
--- a/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/DeadLetterChannel.java
+++ b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/DeadLetterChannel.java
@@ -21,7 +21,6 @@ import java.util.concurrent.ScheduledExecutorService;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Predicate;
 import org.apache.camel.Processor;
-import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
 import org.apache.camel.spi.CamelLogger;
 
 /**
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/DefaultErrorHandler.java b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/DefaultErrorHandler.java
similarity index 97%
rename from core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/DefaultErrorHandler.java
rename to core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/DefaultErrorHandler.java
index 187bd6c..d7b3f51 100644
--- a/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/DefaultErrorHandler.java
+++ b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/DefaultErrorHandler.java
@@ -21,7 +21,6 @@ import java.util.concurrent.ScheduledExecutorService;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Predicate;
 import org.apache.camel.Processor;
-import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
 import org.apache.camel.spi.CamelLogger;
 
 /**
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/DefaultExceptionPolicyStrategy.java
similarity index 75%
rename from core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
rename to core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/DefaultExceptionPolicyStrategy.java
index 3c5b660..f8eebe1 100644
--- a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
+++ b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/DefaultExceptionPolicyStrategy.java
@@ -14,10 +14,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor.exceptionpolicy;
+package org.apache.camel.processor.errorhandler;
 
 import java.util.Iterator;
-import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
@@ -28,17 +29,17 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * The default strategy used in Camel to resolve the {@link ExceptionPolicy} that should
+ * The default strategy used in Camel to resolve the {@link ExceptionPolicyKey} that should
  * handle the thrown exception.
  * <p/>
  * <b>Selection strategy:</b>
  * <br/>This strategy applies the following rules:
  * <ul>
  * <li>Will walk the exception hierarchy from bottom upwards till the thrown exception, meaning that the most outer caused
- * by is selected first, ending with the thrown exception itself. The method {@link #createExceptionIterator(Throwable)}
+ * by is selected first, ending with the thrown exception itself. The method {@link #createExceptionIterable(Throwable)}
  * provides the Iterator used for the walking.</li>
  * <li>The exception type must be configured with an Exception that is an instance of the thrown exception, this
- * is tested using the {@link #filter(ExceptionPolicy, Class, Throwable)} method.
+ * is tested using the {@link #filter(ExceptionPolicyKey, Class, Throwable)} method.
  * By default the filter uses <tt>instanceof</tt> test.</li>
  * <li>If the exception type has <b>exactly</b> the thrown exception then its selected as its an exact match</li>
  * <li>Otherwise the type that has an exception that is the closest super of the thrown exception is selected
@@ -46,8 +47,8 @@ import org.slf4j.LoggerFactory;
  * </ul>
  * <p/>
  * <b>Fine grained matching:</b>
- * <br/> If the {@link ExceptionPolicy} has a when defined with an expression the type is also matches against
- * the current exchange using the {@link #matchesWhen(ExceptionPolicy, org.apache.camel.Exchange)}
+ * <br/> If the {@link ExceptionPolicyKey} has a when defined with an expression the type is also matches against
+ * the current exchange using the {@link #matchesWhen(ExceptionPolicyKey, org.apache.camel.Exchange)}
  * method. This can be used to for more fine grained matching, so you can e.g. define multiple sets of
  * exception types with the same exception class(es) but have a predicate attached to select which to select at runtime.
  */
@@ -55,27 +56,29 @@ public class DefaultExceptionPolicyStrategy implements ExceptionPolicyStrategy {
 
     private static final Logger LOG = LoggerFactory.getLogger(DefaultExceptionPolicyStrategy.class);
 
-    public ExceptionPolicy getExceptionPolicy(Map<ExceptionPolicyKey, ExceptionPolicy> exceptionPolicies,
-                                              Exchange exchange, Throwable exception) {
+    @Override
+    public ExceptionPolicyKey getExceptionPolicy(Set<ExceptionPolicyKey> exceptionPolicies, Exchange exchange, Throwable exception) {
 
-        Map<Integer, ExceptionPolicy> candidates = new TreeMap<>();
-        Map<ExceptionPolicyKey, ExceptionPolicy> routeScoped = new LinkedHashMap<>();
-        Map<ExceptionPolicyKey, ExceptionPolicy> contextScoped = new LinkedHashMap<>();
+        Map<Integer, ExceptionPolicyKey> candidates = new TreeMap<>();
+        Set<ExceptionPolicyKey> routeScoped = new LinkedHashSet<>();
+        Set<ExceptionPolicyKey> contextScoped = new LinkedHashSet<>();
 
         // split policies into route and context scoped
         initRouteAndContextScopedExceptionPolicies(exceptionPolicies, routeScoped, contextScoped);
 
         // at first check route scoped as we prefer them over context scoped
         // recursive up the tree using the iterator
+        Iterable<Throwable> throwables = createExceptionIterable(exception);
+
         boolean exactMatch = false;
-        Iterator<Throwable> it = createExceptionIterator(exception);
+        Iterator<Throwable> it = throwables.iterator();
         while (!exactMatch && it.hasNext()) {
             // we should stop looking if we have found an exact match
             exactMatch = findMatchedExceptionPolicy(routeScoped, exchange, it.next(), candidates);
         }
 
         // fallback to check context scoped (only do this if there was no exact match)
-        it = createExceptionIterator(exception);
+        it = throwables.iterator();
         while (!exactMatch && it.hasNext()) {
             // we should stop looking if we have found an exact match
             exactMatch = findMatchedExceptionPolicy(contextScoped, exchange, it.next(), candidates);
@@ -93,25 +96,24 @@ public class DefaultExceptionPolicyStrategy implements ExceptionPolicyStrategy {
         }
     }
 
-    private void initRouteAndContextScopedExceptionPolicies(Map<ExceptionPolicyKey, ExceptionPolicy> exceptionPolicies,
-                                                            Map<ExceptionPolicyKey, ExceptionPolicy> routeScoped,
-                                                            Map<ExceptionPolicyKey, ExceptionPolicy> contextScoped) {
+    private void initRouteAndContextScopedExceptionPolicies(Set<ExceptionPolicyKey> exceptionPolicies,
+                                                            Set<ExceptionPolicyKey> routeScoped,
+                                                            Set<ExceptionPolicyKey> contextScoped) {
 
         // loop through all the entries and split into route and context scoped
-        Set<Map.Entry<ExceptionPolicyKey, ExceptionPolicy>> entries = exceptionPolicies.entrySet();
-        for (Map.Entry<ExceptionPolicyKey, ExceptionPolicy> entry : entries) {
-            if (entry.getKey().getRouteId() != null) {
-                routeScoped.put(entry.getKey(), entry.getValue());
+        for (ExceptionPolicyKey entry : exceptionPolicies) {
+            if (entry.getRouteId() != null) {
+                routeScoped.add(entry);
             } else {
-                contextScoped.put(entry.getKey(), entry.getValue());
+                contextScoped.add(entry);
             }
         }
     }
 
 
-    private boolean findMatchedExceptionPolicy(Map<ExceptionPolicyKey, ExceptionPolicy> exceptionPolicies,
+    private boolean findMatchedExceptionPolicy(Iterable<ExceptionPolicyKey> exceptionPolicies,
                                                Exchange exchange, Throwable exception,
-                                               Map<Integer, ExceptionPolicy> candidates) {
+                                               Map<Integer, ExceptionPolicyKey> candidates) {
         if (LOG.isTraceEnabled()) {
             LOG.trace("Finding best suited exception policy for thrown exception {}", exception.getClass().getName());
         }
@@ -119,22 +121,20 @@ public class DefaultExceptionPolicyStrategy implements ExceptionPolicyStrategy {
         // 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 to return
-        ExceptionPolicy candidate = null;
+        ExceptionPolicyKey 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<ExceptionPolicyKey, ExceptionPolicy>> entries = exceptionPolicies.entrySet();
-        for (Map.Entry<ExceptionPolicyKey, ExceptionPolicy> entry : entries) {
-            Class<?> clazz = entry.getKey().getExceptionClass();
-            ExceptionPolicy type = entry.getValue();
+        for (ExceptionPolicyKey type : exceptionPolicies) {
+            Class<?> clazz = type.getExceptionClass();
 
             // if ExceptionPolicy is route scoped then the current route (Exchange) must match
             // so we will not pick an ExceptionPolicy from another route
-            if (exchange != null && exchange.getUnitOfWork() != null && type.isRouteScoped()) {
+            String typeRoute = type.getRouteId();
+            if (exchange != null && exchange.getUnitOfWork() != null && ObjectHelper.isNotEmpty(typeRoute)) {
                 String route = exchange.getUnitOfWork().getRouteContext() != null ? exchange.getUnitOfWork().getRouteContext().getRouteId() : null;
-                String typeRoute = type.getRouteId();
-                if (route != null && typeRoute != null && !route.equals(typeRoute)) {
+                if (route != null && !route.equals(typeRoute)) {
                     if (LOG.isTraceEnabled()) {
                         LOG.trace("The type is scoped for route: {} however Exchange is at route: {}", typeRoute, route);
                     }
@@ -200,7 +200,7 @@ public class DefaultExceptionPolicyStrategy implements ExceptionPolicyStrategy {
      * @param exception      the thrown exception
      * @return <tt>true</tt> if the to current exception class is a candidate, <tt>false</tt> to skip it.
      */
-    protected boolean filter(ExceptionPolicy type, Class<?> exceptionClass, Throwable exception) {
+    protected boolean filter(ExceptionPolicyKey type, Class<?> exceptionClass, Throwable exception) {
         // must be instance of check to ensure that the exceptionClass is one type of the thrown exception
         return exceptionClass.isInstance(exception);
     }
@@ -218,26 +218,26 @@ public class DefaultExceptionPolicyStrategy implements ExceptionPolicyStrategy {
      * @param exchange the current {@link Exchange}
      * @return <tt>true</tt> if matched, <tt>false</tt> otherwise.
      */
-    protected boolean matchesWhen(ExceptionPolicy definition, Exchange exchange) {
-        if (definition.getOnWhen() == null || definition.getOnWhen() == null) {
+    protected boolean matchesWhen(ExceptionPolicyKey definition, Exchange exchange) {
+        if (definition.getWhen() == null) {
             // if no predicate then it's always a match
             return true;
         }
-        return definition.getOnWhen().matches(exchange);
+        return definition.getWhen().matches(exchange);
     }
 
     /**
      * Strategy method creating the iterator to walk the exception in the order Camel should use
-     * for find the {@link ExceptionPolicy} should be used.
+     * for find the {@link ExceptionPolicyKey} should be used.
      * <p/>
      * The default iterator will walk from the bottom upwards
      * (the last caused by going upwards to the exception)
      *
      * @param exception  the exception
-     * @return the iterator
+     * @return the list to iterate
      */
-    protected Iterator<Throwable> createExceptionIterator(Throwable exception) {
-        return ObjectHelper.createExceptionIterator(exception);
+    protected Iterable<Throwable> createExceptionIterable(Throwable exception) {
+        return ObjectHelper.createExceptionIterable(exception);
     }
 
     private static int getInheritanceLevel(Class<?> clazz) {
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupport.java b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupport.java
similarity index 89%
rename from core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupport.java
rename to core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupport.java
index 5f8a45f..90fce40 100644
--- a/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupport.java
+++ b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupport.java
@@ -22,10 +22,6 @@ import java.util.Map;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.processor.ErrorHandler;
-import org.apache.camel.processor.exceptionpolicy.DefaultExceptionPolicyStrategy;
-import org.apache.camel.processor.exceptionpolicy.ExceptionPolicy;
-import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyKey;
-import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
 import org.apache.camel.support.ChildServiceSupport;
 
 /**
@@ -44,7 +40,7 @@ public abstract class ErrorHandlerSupport extends ChildServiceSupport implements
         exceptionPolicies.put(key, policy);
     }
 
-    /**
+    /**CamelContextHelper
      * Attempts to find the best suited {@link ExceptionPolicy} to be used for handling the given thrown exception.
      *
      * @param exchange  the exchange
@@ -56,7 +52,8 @@ public abstract class ErrorHandlerSupport extends ChildServiceSupport implements
             throw new IllegalStateException("The exception policy has not been set");
         }
 
-        return exceptionPolicy.getExceptionPolicy(exceptionPolicies, exchange, exception);
+        ExceptionPolicyKey key = exceptionPolicy.getExceptionPolicy(exceptionPolicies.keySet(), exchange, exception);
+        return key != null ? exceptionPolicies.get(key) : null;
     }
 
     /**
diff --git a/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/ExceptionPolicy.java b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/ExceptionPolicy.java
new file mode 100644
index 0000000..cbfdc4a
--- /dev/null
+++ b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/ExceptionPolicy.java
@@ -0,0 +1,261 @@
+/*
+ * 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.errorhandler;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.LoggingLevel;
+import org.apache.camel.Predicate;
+import org.apache.camel.Processor;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.support.CamelContextHelper;
+import org.apache.camel.util.ObjectHelper;
+
+public class ExceptionPolicy {
+
+    private String id;
+    private String routeId;
+    private boolean useOriginalInMessage;
+    private boolean hasOutputs;
+
+    private Predicate handledPolicy;
+    private Predicate continuedPolicy;
+    private Predicate retryWhilePolicy;
+    private Processor onRedelivery;
+    private Processor onExceptionOccurred;
+    private String redeliveryPolicyRef;
+    private Map<RedeliveryOption, String> redeliveryPolicy;
+    private List<String> exceptions;
+
+    public ExceptionPolicy(String id, String routeId, boolean useOriginalInMessage, boolean hasOutputs, Predicate handledPolicy, Predicate continuedPolicy, Predicate retryWhilePolicy, Processor onRedelivery, Processor onExceptionOccurred, String redeliveryPolicyRef, Map<RedeliveryOption, String> redeliveryPolicy, List<String> exceptions) {
+        this.id = id;
+        this.routeId = routeId;
+        this.useOriginalInMessage = useOriginalInMessage;
+        this.hasOutputs = hasOutputs;
+        this.handledPolicy = handledPolicy;
+        this.continuedPolicy = continuedPolicy;
+        this.retryWhilePolicy = retryWhilePolicy;
+        this.onRedelivery = onRedelivery;
+        this.onExceptionOccurred = onExceptionOccurred;
+        this.redeliveryPolicyRef = redeliveryPolicyRef;
+        this.redeliveryPolicy = redeliveryPolicy;
+        this.exceptions = exceptions;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public String getRouteId() {
+        return routeId;
+    }
+
+    public boolean getUseOriginalInMessage() {
+        return useOriginalInMessage;
+    }
+
+    public List<String> getExceptions() {
+        return exceptions;
+    }
+
+    public Predicate getHandledPolicy() {
+        return handledPolicy;
+    }
+
+    public Predicate getContinuedPolicy() {
+        return continuedPolicy;
+    }
+
+    public Predicate getRetryWhilePolicy() {
+        return retryWhilePolicy;
+    }
+
+    public Processor getOnRedelivery() {
+        return onRedelivery;
+    }
+
+    public Processor getOnExceptionOccurred() {
+        return onExceptionOccurred;
+    }
+
+    /**
+     * Allows an exception handler to create a new redelivery policy for this exception type
+     *
+     * @param context      the camel context
+     * @param parentPolicy the current redelivery policy, is newer <tt>null</tt>
+     * @return a newly created redelivery policy, or return the original policy if no customization is required
+     *         for this exception handler.
+     */
+    public RedeliveryPolicy createRedeliveryPolicy(CamelContext context, RedeliveryPolicy parentPolicy) {
+        if (redeliveryPolicyRef != null) {
+            return CamelContextHelper.mandatoryLookup(context, redeliveryPolicyRef, RedeliveryPolicy.class);
+        } else if (redeliveryPolicy != null) {
+            return createRedeliveryPolicy(redeliveryPolicy, context, parentPolicy);
+        } else if (hasOutputs && parentPolicy.getMaximumRedeliveries() != 0) {
+            // if we have outputs, then do not inherit parent maximumRedeliveries
+            // as you would have to explicit configure maximumRedeliveries on this onException to use it
+            // this is the behavior Camel has always had
+            RedeliveryPolicy answer = parentPolicy.copy();
+            answer.setMaximumRedeliveries(0);
+            return answer;
+        } else {
+            return parentPolicy;
+        }
+    }
+
+    public boolean determineIfRedeliveryIsEnabled(CamelContext camelContext) throws Exception {
+        if (redeliveryPolicyRef != null) {
+            // lookup in registry if ref provided
+            RedeliveryPolicy policy = CamelContextHelper.mandatoryLookup(camelContext, redeliveryPolicyRef, RedeliveryPolicy.class);
+            if (policy.getMaximumRedeliveries() != 0) {
+                // must check for != 0 as (-1 means redeliver forever)
+                return true;
+            }
+        } else if (redeliveryPolicy != null) {
+            Integer max = CamelContextHelper.parseInteger(camelContext, redeliveryPolicy.get(RedeliveryOption.maximumRedeliveries));
+            if (max != null && max != 0) {
+                // must check for != 0 as (-1 means redeliver forever)
+                return true;
+            }
+        }
+
+        if (retryWhilePolicy != null) {
+            return true;
+        }
+
+        return false;
+    }
+
+    public enum RedeliveryOption {
+        maximumRedeliveries,
+        redeliveryDelay,
+        asyncDelayedRedelivery,
+        backOffMultiplier,
+        useExponentialBackOff,
+        collisionAvoidanceFactor,
+        useCollisionAvoidance,
+        maximumRedeliveryDelay,
+        retriesExhaustedLogLevel,
+        retryAttemptedLogLevel,
+        retryAttemptedLogInterval,
+        logRetryAttempted,
+        logStackTrace,
+        logRetryStackTrace,
+        logHandled,
+        logNewException,
+        logContinued,
+        logExhausted,
+        logExhaustedMessageHistory,
+        logExhaustedMessageBody,
+        disableRedelivery,
+        delayPattern,
+        allowRedeliveryWhileStopping,
+        exchangeFormatterRef;
+    }
+
+    private static RedeliveryPolicy createRedeliveryPolicy(Map<RedeliveryOption, String> definition, CamelContext context, RedeliveryPolicy parentPolicy) {
+        RedeliveryPolicy answer;
+        if (parentPolicy != null) {
+            answer = parentPolicy.copy();
+        } else {
+            answer = new RedeliveryPolicy();
+        }
+        try {
+            if (definition.get(RedeliveryOption.maximumRedeliveries) != null) {
+                answer.setMaximumRedeliveries(CamelContextHelper.parseInteger(context, definition.get(RedeliveryOption.maximumRedeliveries)));
+            }
+            if (definition.get(RedeliveryOption.redeliveryDelay) != null) {
+                answer.setRedeliveryDelay(CamelContextHelper.parseLong(context, definition.get(RedeliveryOption.redeliveryDelay)));
+            }
+            if (definition.get(RedeliveryOption.asyncDelayedRedelivery) != null) {
+                answer.setAsyncDelayedRedelivery(CamelContextHelper.parseBoolean(context, definition.get(RedeliveryOption.asyncDelayedRedelivery)));
+            }
+            if (definition.get(RedeliveryOption.retriesExhaustedLogLevel) != null) {
+                answer.setRetriesExhaustedLogLevel(LoggingLevel.valueOf(definition.get(RedeliveryOption.retriesExhaustedLogLevel)));
+            }
+            if (definition.get(RedeliveryOption.retryAttemptedLogLevel) != null) {
+                answer.setRetryAttemptedLogLevel(LoggingLevel.valueOf(definition.get(RedeliveryOption.retryAttemptedLogLevel)));
+            }
+            if (definition.get(RedeliveryOption.retryAttemptedLogInterval) != null) {
+                answer.setRetryAttemptedLogInterval(CamelContextHelper.parseInteger(context, definition.get(RedeliveryOption.retryAttemptedLogInterval)));
+            }
+            if (definition.get(RedeliveryOption.backOffMultiplier) != null) {
+                answer.setBackOffMultiplier(CamelContextHelper.parseDouble(context, definition.get(RedeliveryOption.backOffMultiplier)));
+            }
+            if (definition.get(RedeliveryOption.useExponentialBackOff) != null) {
+                answer.setUseExponentialBackOff(CamelContextHelper.parseBoolean(context, definition.get(RedeliveryOption.useExponentialBackOff)));
+            }
+            if (definition.get(RedeliveryOption.collisionAvoidanceFactor) != null) {
+                answer.setCollisionAvoidanceFactor(CamelContextHelper.parseDouble(context, definition.get(RedeliveryOption.collisionAvoidanceFactor)));
+            }
+            if (definition.get(RedeliveryOption.useCollisionAvoidance) != null) {
+                answer.setUseCollisionAvoidance(CamelContextHelper.parseBoolean(context, definition.get(RedeliveryOption.useCollisionAvoidance)));
+            }
+            if (definition.get(RedeliveryOption.maximumRedeliveryDelay) != null) {
+                answer.setMaximumRedeliveryDelay(CamelContextHelper.parseLong(context, definition.get(RedeliveryOption.maximumRedeliveryDelay)));
+            }
+            if (definition.get(RedeliveryOption.logStackTrace) != null) {
+                answer.setLogStackTrace(CamelContextHelper.parseBoolean(context, definition.get(RedeliveryOption.logStackTrace)));
+            }
+            if (definition.get(RedeliveryOption.logRetryStackTrace) != null) {
+                answer.setLogRetryStackTrace(CamelContextHelper.parseBoolean(context, definition.get(RedeliveryOption.logRetryStackTrace)));
+            }
+            if (definition.get(RedeliveryOption.logHandled) != null) {
+                answer.setLogHandled(CamelContextHelper.parseBoolean(context, definition.get(RedeliveryOption.logHandled)));
+            }
+            if (definition.get(RedeliveryOption.logNewException) != null) {
+                answer.setLogNewException(CamelContextHelper.parseBoolean(context, definition.get(RedeliveryOption.logNewException)));
+            }
+            if (definition.get(RedeliveryOption.logContinued) != null) {
+                answer.setLogContinued(CamelContextHelper.parseBoolean(context, definition.get(RedeliveryOption.logContinued)));
+            }
+            if (definition.get(RedeliveryOption.logRetryAttempted) != null) {
+                answer.setLogRetryAttempted(CamelContextHelper.parseBoolean(context, definition.get(RedeliveryOption.logRetryAttempted)));
+            }
+            if (definition.get(RedeliveryOption.logExhausted) != null) {
+                answer.setLogExhausted(CamelContextHelper.parseBoolean(context, definition.get(RedeliveryOption.logExhausted)));
+            }
+            if (definition.get(RedeliveryOption.logExhaustedMessageHistory) != null) {
+                answer.setLogExhaustedMessageHistory(CamelContextHelper.parseBoolean(context, definition.get(RedeliveryOption.logExhaustedMessageHistory)));
+            }
+            if (definition.get(RedeliveryOption.logExhaustedMessageBody) != null) {
+                answer.setLogExhaustedMessageBody(CamelContextHelper.parseBoolean(context, definition.get(RedeliveryOption.logExhaustedMessageBody)));
+            }
+            if (definition.get(RedeliveryOption.disableRedelivery) != null) {
+                if (CamelContextHelper.parseBoolean(context, definition.get(RedeliveryOption.disableRedelivery))) {
+                    answer.setMaximumRedeliveries(0);
+                }
+            }
+            if (definition.get(RedeliveryOption.delayPattern) != null) {
+                answer.setDelayPattern(CamelContextHelper.parseText(context, definition.get(RedeliveryOption.delayPattern)));
+            }
+            if (definition.get(RedeliveryOption.allowRedeliveryWhileStopping) != null) {
+                answer.setAllowRedeliveryWhileStopping(CamelContextHelper.parseBoolean(context, definition.get(RedeliveryOption.allowRedeliveryWhileStopping)));
+            }
+            if (definition.get(RedeliveryOption.exchangeFormatterRef) != null) {
+                answer.setExchangeFormatterRef(CamelContextHelper.parseText(context, definition.get(RedeliveryOption.exchangeFormatterRef)));
+            }
+        } catch (Exception e) {
+            throw RuntimeCamelException.wrapRuntimeCamelException(e);
+        }
+
+        return answer;
+    }
+
+}
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyKey.java b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/ExceptionPolicyKey.java
similarity index 95%
rename from core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyKey.java
rename to core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/ExceptionPolicyKey.java
index 8efdf59..368e0c2 100644
--- a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyKey.java
+++ b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/ExceptionPolicyKey.java
@@ -14,13 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor.exceptionpolicy;
+package org.apache.camel.processor.errorhandler;
 
 import org.apache.camel.Predicate;
 
 /**
  * Exception policy key is a compound key for storing:
- * <b>route id </b> + <b>exception class</b> + <b>when</b> => <b>exception type</b>.
+ * <b>route id</b> + <b>exception class</b> + <b>when</b> => <b>exception type</b>.
  * <p/>
  * This is used by Camel to store the onException types configured that has or has not predicates attached (when).
  */
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/ExceptionPolicyStrategy.java
similarity index 69%
rename from core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java
rename to core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/ExceptionPolicyStrategy.java
index 482085a..7cad346 100644
--- a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java
+++ b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/ExceptionPolicyStrategy.java
@@ -14,29 +14,28 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor.exceptionpolicy;
+package org.apache.camel.processor.errorhandler;
 
-import java.util.Map;
+import java.util.Set;
 
 import org.apache.camel.Exchange;
 
 /**
- * A strategy to determine which {@link ExceptionPolicy} should handle the thrown
+ * A strategy to determine which {@link ExceptionPolicyKey} should handle the thrown
  * exception.
  *
- * @see org.apache.camel.processor.exceptionpolicy.DefaultExceptionPolicyStrategy DefaultExceptionPolicy
+ * @see DefaultExceptionPolicyStrategy DefaultExceptionPolicy
  */
 public interface ExceptionPolicyStrategy {
 
     /**
-     * Resolves the {@link ExceptionPolicy} that should handle the thrown exception.
+     * Resolves the {@link ExceptionPolicyKey} that should handle the thrown exception.
      *
      * @param exceptionPolicies 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.
      */
-    ExceptionPolicy getExceptionPolicy(Map<ExceptionPolicyKey, ExceptionPolicy> exceptionPolicies,
-                                       Exchange exchange, Throwable exception);
+    ExceptionPolicyKey getExceptionPolicy(Set<ExceptionPolicyKey> exceptionPolicies, Exchange exchange, Throwable exception);
 
 }
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryErrorHandler.java b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryErrorHandler.java
similarity index 99%
rename from core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryErrorHandler.java
rename to core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryErrorHandler.java
index 17d5423..782d8a7 100644
--- a/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryErrorHandler.java
+++ b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryErrorHandler.java
@@ -36,7 +36,6 @@ import org.apache.camel.Navigate;
 import org.apache.camel.Predicate;
 import org.apache.camel.Processor;
 import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.processor.exceptionpolicy.ExceptionPolicy;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.CamelLogger;
 import org.apache.camel.spi.ExchangeFormatter;
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryPolicy.java b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryPolicy.java
similarity index 100%
rename from core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryPolicy.java
rename to core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryPolicy.java
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/package.html b/core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/package.html
similarity index 100%
rename from core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/package.html
rename to core/camel-base/src/main/java/org/apache/camel/processor/errorhandler/package.html
diff --git a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java
index 574c147..e4c87a8 100644
--- a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java
+++ b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java
@@ -21,7 +21,7 @@ import java.util.List;
 import org.apache.camel.ErrorHandlerFactory;
 import org.apache.camel.model.OnExceptionDefinition;
 import org.apache.camel.processor.ErrorHandler;
-import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
+import org.apache.camel.processor.errorhandler.ExceptionPolicyStrategy;
 import org.apache.camel.spi.RouteContext;
 
 /**
diff --git a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java
index 217351d..a0e86e2 100644
--- a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java
+++ b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java
@@ -30,9 +30,10 @@ import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.processor.ErrorHandler;
 import org.apache.camel.processor.errorhandler.ErrorHandlerSupport;
 import org.apache.camel.processor.errorhandler.RedeliveryErrorHandler;
-import org.apache.camel.processor.exceptionpolicy.ExceptionPolicy;
-import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyKey;
-import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
+import org.apache.camel.processor.errorhandler.ExceptionPolicy;
+import org.apache.camel.processor.errorhandler.ExceptionPolicyKey;
+import org.apache.camel.processor.errorhandler.ExceptionPolicyStrategy;
+import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
 import org.apache.camel.spi.ClassResolver;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.util.ObjectHelper;
@@ -87,7 +88,7 @@ public abstract class ErrorHandlerBuilderSupport implements ErrorHandlerBuilder
 
             // load exception classes
             List<Class<? extends Throwable>> list;
-            if (exceptionType.getExceptions() != null && !exceptionType.getExceptions().isEmpty()) {
+            if (ObjectHelper.isNotEmpty(exceptionType.getExceptions())) {
                 list = createExceptionClasses(exceptionType, routeContext.getCamelContext().getClassResolver());
                 for (Class<? extends Throwable> clazz : list) {
                     String routeId = null;
@@ -100,15 +101,15 @@ public abstract class ErrorHandlerBuilderSupport implements ErrorHandlerBuilder
                     }
                     Predicate when = exceptionType.getOnWhen() != null ? exceptionType.getOnWhen().getExpression() : null;
                     ExceptionPolicyKey key = new ExceptionPolicyKey(routeId, clazz, when);
-                    ExceptionPolicy policy = toExceptionPolicy(exceptionType);
+                    ExceptionPolicy policy = toExceptionPolicy(exceptionType, routeContext);
                     handlerSupport.addExceptionPolicy(key, policy);
                 }
             }
         }
     }
 
-    protected static ExceptionPolicy toExceptionPolicy(OnExceptionDefinition exceptionType) {
-        return new ExceptionPolicy(exceptionType);
+    protected static ExceptionPolicy toExceptionPolicy(OnExceptionDefinition exceptionType, RouteContext routeContext) {
+        return ErrorHandlerReifier.createExceptionPolicy(exceptionType, routeContext);
     }
 
     protected static List<Class<? extends Throwable>> createExceptionClasses(OnExceptionDefinition exceptionType, ClassResolver resolver) {
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicy.java b/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicy.java
deleted file mode 100644
index cb0cecd..0000000
--- a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicy.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.apache.camel.processor.exceptionpolicy;
-
-import java.util.List;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.Predicate;
-import org.apache.camel.Processor;
-import org.apache.camel.model.OnExceptionDefinition;
-import org.apache.camel.model.ProcessorDefinitionHelper;
-import org.apache.camel.model.RedeliveryPolicyDefinition;
-import org.apache.camel.processor.errorhandler.RedeliveryPolicy;
-import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
-
-public class ExceptionPolicy {
-
-    private final OnExceptionDefinition def;
-
-    public ExceptionPolicy(OnExceptionDefinition def) {
-        this.def = def;
-    }
-
-    public String getId() {
-        return def.getId();
-    }
-
-    public String getRouteId() {
-        return ProcessorDefinitionHelper.getRouteId(def);
-    }
-
-    public boolean isRouteScoped() {
-        return def.getRouteScoped() != null && def.getRouteScoped();
-    }
-
-    public Predicate getOnWhen() {
-        return def.getOnWhen() != null ? def.getOnWhen().getExpression() : null;
-    }
-
-    public String getRedeliveryPolicyRef() {
-        return def.getRedeliveryPolicyRef();
-    }
-
-    public boolean hasOutputs() {
-        return def.getOutputs() != null && !def.getOutputs().isEmpty();
-    }
-
-    public RedeliveryPolicyDefinition getRedeliveryPolicyType() {
-        return def.getRedeliveryPolicyType();
-    }
-
-    public Predicate getHandledPolicy() {
-        return def.getHandledPolicy();
-    }
-
-    public Predicate getContinuedPolicy() {
-        return def.getContinuedPolicy();
-    }
-
-    public Predicate getRetryWhilePolicy() {
-        return def.getRetryWhilePolicy();
-    }
-
-    public boolean getUseOriginalInMessage() {
-        return def.getUseOriginalMessagePolicy() != null && def.getUseOriginalMessagePolicy();
-    }
-
-    public Processor getOnRedelivery() {
-        return def.getOnRedelivery();
-    }
-
-    public Processor getOnExceptionOccurred() {
-        return def.getOnExceptionOccurred();
-    }
-
-    public List<String> getExceptions() {
-        return def.getExceptions();
-    }
-
-    public boolean determineIfRedeliveryIsEnabled(CamelContext context) throws Exception {
-        return ErrorHandlerReifier.determineIfRedeliveryIsEnabled(this, context);
-    }
-
-    public RedeliveryPolicy createRedeliveryPolicy(CamelContext context, RedeliveryPolicy parent) {
-        return ErrorHandlerReifier.createRedeliveryPolicy(this, context, parent);
-    }
-}
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java
index f030abd..557e291 100644
--- a/core/camel-core/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java
@@ -49,7 +49,7 @@ class DynamicRouterReifier extends ExpressionReifier<DynamicRouterDefinition<?>>
         // and wrap this in an error handler
         ErrorHandlerFactory builder = routeContext.getErrorHandlerFactory();
         // create error handler (create error handler directly to keep it light weight,
-        // instead of using ProcessorDefinition.wrapInErrorHandler)
+        // instead of using ProcessorReifier.wrapInErrorHandler)
         AsyncProcessor errorHandler = (AsyncProcessor) ErrorHandlerReifier.reifier(builder).createErrorHandler(routeContext, dynamicRouter.newRoutingSlipProcessorForErrorHandler());
         dynamicRouter.setErrorHandler(errorHandler);
 
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/OnExceptionReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/OnExceptionReifier.java
index 82e5ec7..98d19f8 100644
--- a/core/camel-core/src/main/java/org/apache/camel/reifier/OnExceptionReifier.java
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/OnExceptionReifier.java
@@ -26,7 +26,6 @@ import org.apache.camel.model.OnExceptionDefinition;
 import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.processor.CatchProcessor;
 import org.apache.camel.processor.FatalFallbackErrorHandler;
-import org.apache.camel.processor.exceptionpolicy.ExceptionPolicy;
 import org.apache.camel.spi.ClassResolver;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.support.CamelContextHelper;
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/DefaultErrorHandlerReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/DefaultErrorHandlerReifier.java
index a262509a..7fcb02b 100644
--- a/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/DefaultErrorHandlerReifier.java
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/DefaultErrorHandlerReifier.java
@@ -1,21 +1,15 @@
 package org.apache.camel.reifier.errorhandler;
 
-import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ScheduledExecutorService;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.Endpoint;
 import org.apache.camel.ErrorHandlerFactory;
-import org.apache.camel.NoSuchEndpointException;
 import org.apache.camel.Processor;
-import org.apache.camel.builder.DeadLetterChannelBuilder;
 import org.apache.camel.builder.DefaultErrorHandlerBuilder;
-import org.apache.camel.processor.errorhandler.DeadLetterChannel;
 import org.apache.camel.processor.errorhandler.DefaultErrorHandler;
 import org.apache.camel.spi.ExecutorServiceManager;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.spi.ThreadPoolProfile;
-import org.apache.camel.util.StringHelper;
 
 public class DefaultErrorHandlerReifier<T extends DefaultErrorHandlerBuilder> extends ErrorHandlerReifier<T> {
 
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java
index c0b90c4..ca15e64 100644
--- a/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java
@@ -19,8 +19,6 @@ package org.apache.camel.reifier.errorhandler;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.ScheduledExecutorService;
 import java.util.function.Function;
 
 import org.apache.camel.CamelContext;
@@ -35,12 +33,14 @@ import org.apache.camel.builder.NoErrorHandlerBuilder;
 import org.apache.camel.model.OnExceptionDefinition;
 import org.apache.camel.model.RedeliveryPolicyDefinition;
 import org.apache.camel.processor.ErrorHandler;
+import org.apache.camel.processor.errorhandler.ExceptionPolicy;
+import org.apache.camel.processor.errorhandler.ExceptionPolicy.RedeliveryOption;
 import org.apache.camel.processor.errorhandler.ErrorHandlerSupport;
 import org.apache.camel.processor.errorhandler.RedeliveryErrorHandler;
 import org.apache.camel.processor.errorhandler.RedeliveryPolicy;
-import org.apache.camel.processor.exceptionpolicy.ExceptionPolicy;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.support.CamelContextHelper;
+import org.apache.camel.util.ObjectHelper;
 
 public abstract class ErrorHandlerReifier<T extends ErrorHandlerBuilderSupport> {
 
@@ -83,6 +83,60 @@ public abstract class ErrorHandlerReifier<T extends ErrorHandlerBuilderSupport>
         }
     }
 
+    public static ExceptionPolicy createExceptionPolicy(OnExceptionDefinition def, RouteContext routeContext) {
+        return new ExceptionPolicy(
+                def.getId(),
+                CamelContextHelper.getRouteId(def),
+                def.getUseOriginalMessagePolicy() != null && def.getUseOriginalMessagePolicy(),
+                ObjectHelper.isNotEmpty(def.getOutputs()),
+                def.getHandledPolicy(),
+                def.getContinuedPolicy(),
+                def.getRetryWhilePolicy(),
+                def.getOnRedelivery(),
+                def.getOnExceptionOccurred(),
+                def.getRedeliveryPolicyRef(),
+                getRedeliveryPolicy(def.getRedeliveryPolicyType()),
+                def.getExceptions());
+    }
+
+    private static Map<RedeliveryOption, String> getRedeliveryPolicy(RedeliveryPolicyDefinition definition) {
+        if (definition == null) {
+            return null;
+        }
+        Map<RedeliveryOption, String> policy = new HashMap<>();
+        setoption(policy, RedeliveryOption.maximumRedeliveries, definition.getMaximumRedeliveries());
+        setoption(policy, RedeliveryOption.redeliveryDelay, definition.getRedeliveryDelay());
+        setoption(policy, RedeliveryOption.asyncDelayedRedelivery, definition.getAsyncDelayedRedelivery());
+        setoption(policy, RedeliveryOption.backOffMultiplier, definition.getBackOffMultiplier());
+        setoption(policy, RedeliveryOption.useExponentialBackOff, definition.getUseExponentialBackOff());
+        setoption(policy, RedeliveryOption.collisionAvoidanceFactor, definition.getCollisionAvoidanceFactor());
+        setoption(policy, RedeliveryOption.useCollisionAvoidance, definition.getUseCollisionAvoidance());
+        setoption(policy, RedeliveryOption.maximumRedeliveryDelay, definition.getMaximumRedeliveryDelay());
+        setoption(policy, RedeliveryOption.retriesExhaustedLogLevel, definition.getRetriesExhaustedLogLevel());
+        setoption(policy, RedeliveryOption.retryAttemptedLogLevel, definition.getRetryAttemptedLogLevel());
+        setoption(policy, RedeliveryOption.retryAttemptedLogInterval, definition.getRetryAttemptedLogInterval());
+        setoption(policy, RedeliveryOption.logRetryAttempted, definition.getLogRetryAttempted());
+        setoption(policy, RedeliveryOption.logStackTrace, definition.getLogStackTrace());
+        setoption(policy, RedeliveryOption.logRetryStackTrace, definition.getLogRetryStackTrace());
+        setoption(policy, RedeliveryOption.logHandled, definition.getLogHandled());
+        setoption(policy, RedeliveryOption.logNewException, definition.getLogNewException());
+        setoption(policy, RedeliveryOption.logContinued, definition.getLogContinued());
+        setoption(policy, RedeliveryOption.logExhausted, definition.getLogExhausted());
+        setoption(policy, RedeliveryOption.logExhaustedMessageHistory, definition.getLogExhaustedMessageHistory());
+        setoption(policy, RedeliveryOption.logExhaustedMessageBody, definition.getLogExhaustedMessageBody());
+        setoption(policy, RedeliveryOption.disableRedelivery, definition.getDisableRedelivery());
+        setoption(policy, RedeliveryOption.delayPattern, definition.getDelayPattern());
+        setoption(policy, RedeliveryOption.allowRedeliveryWhileStopping, definition.getAllowRedeliveryWhileStopping());
+        setoption(policy, RedeliveryOption.exchangeFormatterRef, definition.getExchangeFormatterRef());
+        return policy;
+    }
+
+    private static void setoption(Map<RedeliveryOption, String> policy, RedeliveryOption option, Object value) {
+        if (value != null) {
+            policy.put(option, value.toString());
+        }
+    }
+
     /**
      * Creates the error handler
      *
@@ -206,53 +260,4 @@ public abstract class ErrorHandlerReifier<T extends ErrorHandlerBuilderSupport>
         return answer;
     }
 
-    /**
-     * Allows an exception handler to create a new redelivery policy for this exception type
-     *
-     * @param definition
-     * @param context      the camel context
-     * @param parentPolicy the current redelivery policy, is newer <tt>null</tt>
-     * @return a newly created redelivery policy, or return the original policy if no customization is required
-     *         for this exception handler.
-     */
-    public static RedeliveryPolicy createRedeliveryPolicy(ExceptionPolicy definition, CamelContext context, RedeliveryPolicy parentPolicy) {
-        if (definition.getRedeliveryPolicyRef() != null) {
-            return CamelContextHelper.mandatoryLookup(context, definition.getRedeliveryPolicyRef(), RedeliveryPolicy.class);
-        } else if (definition.getRedeliveryPolicyType() != null) {
-            return createRedeliveryPolicy(definition.getRedeliveryPolicyType(), context, parentPolicy);
-        } else if (definition.hasOutputs() && parentPolicy.getMaximumRedeliveries() != 0) {
-            // if we have outputs, then do not inherit parent maximumRedeliveries
-            // as you would have to explicit configure maximumRedeliveries on this onException to use it
-            // this is the behavior Camel has always had
-            RedeliveryPolicy answer = parentPolicy.copy();
-            answer.setMaximumRedeliveries(0);
-            return answer;
-        } else {
-            return parentPolicy;
-        }
-    }
-
-    public static boolean determineIfRedeliveryIsEnabled(ExceptionPolicy def, CamelContext camelContext) throws Exception {
-        String ref = def.getRedeliveryPolicyRef();
-        if (ref != null) {
-            // lookup in registry if ref provided
-            RedeliveryPolicy policy = CamelContextHelper.mandatoryLookup(camelContext, ref, RedeliveryPolicy.class);
-            if (policy.getMaximumRedeliveries() != 0) {
-                // must check for != 0 as (-1 means redeliver forever)
-                return true;
-            }
-        } else if (def.getRedeliveryPolicyType() != null) {
-            Integer max = CamelContextHelper.parseInteger(camelContext, def.getRedeliveryPolicyType().getMaximumRedeliveries());
-            if (max != null && max != 0) {
-                // must check for != 0 as (-1 means redeliver forever)
-                return true;
-            }
-        }
-
-        if (def.getRetryWhilePolicy() != null) {
-            return true;
-        }
-
-        return false;
-    }
 }
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
index f6cb8b8..a969348 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
@@ -16,7 +16,7 @@
  */
 package org.apache.camel.processor.exceptionpolicy;
 
-import java.util.Map;
+import java.util.Set;
 
 import org.apache.camel.CamelException;
 import org.apache.camel.CamelExchangeException;
@@ -25,6 +25,8 @@ 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.processor.errorhandler.ExceptionPolicyKey;
+import org.apache.camel.processor.errorhandler.ExceptionPolicyStrategy;
 import org.junit.Test;
 
 /**
@@ -42,12 +44,12 @@ public class CustomExceptionPolicyStrategyTest extends ContextTestSupport {
     // START SNIPPET e2
     public static class MyPolicy implements ExceptionPolicyStrategy {
 
-        public ExceptionPolicy getExceptionPolicy(Map<ExceptionPolicyKey, ExceptionPolicy> exceptionPolicices,
-                                                Exchange exchange,
-                                                Throwable exception) {
+        public ExceptionPolicyKey getExceptionPolicy(Set<ExceptionPolicyKey> exceptionPolicices,
+                                                     Exchange exchange,
+                                                     Throwable exception) {
             // This is just an example that always forces the exception type configured
             // with MyPolicyException to win.
-            return exceptionPolicices.get(new ExceptionPolicyKey(null, MyPolicyException.class, null));
+            return new ExceptionPolicyKey(null, MyPolicyException.class, null);
         }
     }
     // END SNIPPET e2
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java
index af8ef8a..280e608 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java
@@ -29,6 +29,10 @@ import org.apache.camel.ExchangeTimedOutException;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.ValidationException;
 import org.apache.camel.model.OnExceptionDefinition;
+import org.apache.camel.processor.errorhandler.DefaultExceptionPolicyStrategy;
+import org.apache.camel.processor.errorhandler.ExceptionPolicy;
+import org.apache.camel.processor.errorhandler.ExceptionPolicyKey;
+import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -43,12 +47,16 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
     private ExceptionPolicy type2;
     private ExceptionPolicy type3;
 
+    private ExceptionPolicy exceptionPolicy(Class<? extends Throwable> exceptionClass) {
+        return ErrorHandlerReifier.createExceptionPolicy(new OnExceptionDefinition(exceptionClass), null);
+    }
+
     private void setupPolicies() {
         strategy = new DefaultExceptionPolicyStrategy();
         policies = new HashMap<>();
-        type1 = new ExceptionPolicy(new OnExceptionDefinition(CamelExchangeException.class));
-        type2 = new ExceptionPolicy(new OnExceptionDefinition(Exception.class));
-        type3 = new ExceptionPolicy(new OnExceptionDefinition(IOException.class));
+        type1 = exceptionPolicy(CamelExchangeException.class);
+        type2 = exceptionPolicy(Exception.class);
+        type3 = exceptionPolicy(IOException.class);
         policies.put(new ExceptionPolicyKey(null, CamelExchangeException.class, null), type1);
         policies.put(new ExceptionPolicyKey(null, Exception.class, null), type2);
         policies.put(new ExceptionPolicyKey(null, IOException.class, null), type3);
@@ -58,8 +66,8 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
         // without the top level exception that can be used as fallback
         strategy = new DefaultExceptionPolicyStrategy();
         policies = new HashMap<>();
-        type1 = new ExceptionPolicy(new OnExceptionDefinition(CamelExchangeException.class));
-        type3 = new ExceptionPolicy(new OnExceptionDefinition(IOException.class));
+        type1 = exceptionPolicy(CamelExchangeException.class);
+        type3 = exceptionPolicy(IOException.class);
         policies.put(new ExceptionPolicyKey(null, CamelExchangeException.class, null), type1);
         policies.put(new ExceptionPolicyKey(null, IOException.class, null), type3);
     }
@@ -67,82 +75,87 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
     private void setupPoliciesCausedBy() {
         strategy = new DefaultExceptionPolicyStrategy();
         policies = new HashMap<>();
-        type1 = new ExceptionPolicy(new OnExceptionDefinition(FileNotFoundException.class));
-        type2 = new ExceptionPolicy(new OnExceptionDefinition(ConnectException.class));
-        type3 = new ExceptionPolicy(new OnExceptionDefinition(IOException.class));
+        type1 = exceptionPolicy(FileNotFoundException.class);
+        type2 = exceptionPolicy(ConnectException.class);
+        type3 = exceptionPolicy(IOException.class);
         policies.put(new ExceptionPolicyKey(null, FileNotFoundException.class, null), type1);
         policies.put(new ExceptionPolicyKey(null, IOException.class, null), type2);
         policies.put(new ExceptionPolicyKey(null, ConnectException.class, null), type3);
     }
+    
+    private ExceptionPolicy findPolicy(Exception exception) {
+        ExceptionPolicyKey key = strategy.getExceptionPolicy(policies.keySet(), null, exception);
+        return policies.get(key);
+    }
 
     @Test
     public void testDirectMatch1() {
         setupPolicies();
-        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new CamelExchangeException("", null));
+        ExceptionPolicy result = findPolicy(new CamelExchangeException("", null));
         assertEquals(type1, result);
     }
 
     @Test
     public void testDirectMatch2() {
         setupPolicies();
-        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new Exception(""));
+        ExceptionPolicy result = findPolicy(new Exception(""));
         assertEquals(type2, result);
     }
 
     @Test
     public void testDirectMatch3() {
         setupPolicies();
-        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new IOException(""));
+        ExceptionPolicy result = findPolicy(new IOException(""));
         assertEquals(type3, result);
     }
 
     @Test
     public void testClosetMatch3() {
         setupPolicies();
-        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new ConnectException(""));
+        ExceptionPolicy result = findPolicy(new ConnectException(""));
         assertEquals(type3, result);
 
-        result = strategy.getExceptionPolicy(policies, null, new SocketException(""));
+        result = findPolicy(new SocketException(""));
         assertEquals(type3, result);
 
-        result = strategy.getExceptionPolicy(policies, null, new FileNotFoundException());
+        result = findPolicy(new FileNotFoundException());
         assertEquals(type3, result);
     }
 
     @Test
     public void testClosetMatch2() {
         setupPolicies();
-        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new ClassCastException(""));
+        ExceptionPolicy result = findPolicy(new ClassCastException(""));
         assertEquals(type2, result);
 
-        result = strategy.getExceptionPolicy(policies, null, new NumberFormatException(""));
+        result = findPolicy(new NumberFormatException(""));
         assertEquals(type2, result);
 
-        result = strategy.getExceptionPolicy(policies, null, new NullPointerException());
+        result = findPolicy(new NullPointerException());
         assertEquals(type2, result);
     }
 
     @Test
     public void testClosetMatch1() {
         setupPolicies();
-        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new ValidationException(null, ""));
+        ExceptionPolicy result = findPolicy(new ValidationException(null, ""));
         assertEquals(type1, result);
 
-        result = strategy.getExceptionPolicy(policies, null, new ExchangeTimedOutException(null, 0));
+        result = findPolicy(new ExchangeTimedOutException(null, 0));
         assertEquals(type1, result);
     }
 
     @Test
     public void testNoMatch1ThenMatchingJustException() {
         setupPolicies();
-        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new AlreadyStoppedException());
+        ExceptionPolicy result = findPolicy(new AlreadyStoppedException());
         assertEquals(type2, result);
     }
 
     @Test
     public void testNoMatch1ThenNull() {
         setupPoliciesNoTopLevelException();
-        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new AlreadyStoppedException());
+        ExceptionPolicy result = findPolicy(new AlreadyStoppedException());
         assertNull("Should not find an exception policy to use", result);
     }
 
@@ -152,7 +165,7 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
 
         IOException ioe = new IOException("Damm");
         ioe.initCause(new FileNotFoundException("Somefile not found"));
-        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, ioe);
+        ExceptionPolicy result = findPolicy(ioe);
         assertEquals(type1, result);
     }
 
@@ -162,7 +175,7 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
 
         IOException ioe = new IOException("Damm");
         ioe.initCause(new FileNotFoundException("Somefile not found"));
-        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new RuntimeCamelException(ioe));
+        ExceptionPolicy result = findPolicy(new RuntimeCamelException(ioe));
         assertEquals(type1, result);
     }
 
@@ -172,7 +185,7 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
 
         IOException ioe = new IOException("Damm");
         ioe.initCause(new ConnectException("Not connected"));
-        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, ioe);
+        ExceptionPolicy result = findPolicy(ioe);
         assertEquals(type3, result);
     }
 
@@ -182,7 +195,7 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
 
         IOException ioe = new IOException("Damm");
         ioe.initCause(new MalformedURLException("Bad url"));
-        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, ioe);
+        ExceptionPolicy result = findPolicy(ioe);
         assertEquals(type2, result);
     }
 


[camel] 05/07: Use custom ports for management tests

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 8f5f59f5dcb8ffa1547afb20cd63bfadaeba365b
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Tue May 28 11:36:30 2019 +0200

    Use custom ports for management tests
---
 .../camel/management/ManagedComponentTest.java     |   3 +-
 .../camel/management/ManagementTestSupport.java    |  19 +++
 .../camel/management/util/AvailablePortFinder.java | 167 +++++++++++++++++++++
 3 files changed, 187 insertions(+), 2 deletions(-)

diff --git a/core/camel-management-impl/src/test/java/org/apache/camel/management/ManagedComponentTest.java b/core/camel-management-impl/src/test/java/org/apache/camel/management/ManagedComponentTest.java
index acbea64..b78f6c4 100644
--- a/core/camel-management-impl/src/test/java/org/apache/camel/management/ManagedComponentTest.java
+++ b/core/camel-management-impl/src/test/java/org/apache/camel/management/ManagedComponentTest.java
@@ -80,8 +80,7 @@ public class ManagedComponentTest extends ManagementTestSupport {
             return;
         }
 
-        JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi/camel"));
-        MBeanServerConnection mbeanServer = connector.getMBeanServerConnection();
+        MBeanServerConnection mbeanServer = getMBeanServer();
 
         ObjectName on = ObjectName.getInstance("org.apache.camel:context=camel-1,type=components,name=\"my-verifiable-component\"");
         assertTrue(mbeanServer.isRegistered(on));
diff --git a/core/camel-management-impl/src/test/java/org/apache/camel/management/ManagementTestSupport.java b/core/camel-management-impl/src/test/java/org/apache/camel/management/ManagementTestSupport.java
index 2965622..a4057bd 100644
--- a/core/camel-management-impl/src/test/java/org/apache/camel/management/ManagementTestSupport.java
+++ b/core/camel-management-impl/src/test/java/org/apache/camel/management/ManagementTestSupport.java
@@ -17,6 +17,7 @@
 package org.apache.camel.management;
 
 import java.io.IOException;
+import java.util.Random;
 
 import javax.management.InstanceNotFoundException;
 import javax.management.MBeanException;
@@ -26,17 +27,35 @@ import javax.management.ObjectName;
 import javax.management.ReflectionException;
 
 import org.apache.camel.ContextTestSupport;
+import org.apache.camel.api.management.JmxSystemPropertyKeys;
+import org.apache.camel.management.util.AvailablePortFinder;
+import org.junit.Before;
 
 /**
  * Base class for JMX tests.
  */
 public abstract class ManagementTestSupport extends ContextTestSupport {
 
+    protected int registryPort;
+    protected String url;
+
     @Override
     protected boolean useJmx() {
         return true;
     }
 
+    @Override
+    @Before
+    public void setUp() throws Exception {
+        registryPort = AvailablePortFinder.getNextAvailable();
+        log.info("Using port " + registryPort);
+
+        // need to explicit set it to false to use non-platform mbs
+        System.setProperty(JmxSystemPropertyKeys.CREATE_CONNECTOR, "true");
+        System.setProperty(JmxSystemPropertyKeys.REGISTRY_PORT, "" + registryPort);
+        super.setUp();
+    }
+
     protected MBeanServer getMBeanServer() {
         return context.getManagementStrategy().getManagementAgent().getMBeanServer();
     }
diff --git a/core/camel-management-impl/src/test/java/org/apache/camel/management/util/AvailablePortFinder.java b/core/camel-management-impl/src/test/java/org/apache/camel/management/util/AvailablePortFinder.java
new file mode 100644
index 0000000..04a14b2
--- /dev/null
+++ b/core/camel-management-impl/src/test/java/org/apache/camel/management/util/AvailablePortFinder.java
@@ -0,0 +1,167 @@
+/*
+ * 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.management.util;
+
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.ServerSocket;
+import java.util.NoSuchElementException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Finds currently available server ports.
+ */
+public final class AvailablePortFinder {
+
+    /**
+     * The minimum server currentMinPort number for IPv4.
+     * Set at 1100 to avoid returning privileged currentMinPort numbers.
+     */
+    public static final int MIN_PORT_NUMBER = 1100;
+
+    /**
+     * The maximum server currentMinPort number for IPv4.
+     */
+    public static final int MAX_PORT_NUMBER = 65535;
+
+    private static final Logger LOG = LoggerFactory.getLogger(AvailablePortFinder.class);
+
+    /**
+     * We'll hold open the lowest port in this process
+     * so parallel processes won't use the same block
+     * of ports.   They'll go up to the next block.
+     */
+    private static final ServerSocket LOCK;
+
+    /**
+     * Incremented to the next lowest available port when getNextAvailable() is called.
+     */
+    private static AtomicInteger currentMinPort = new AtomicInteger(MIN_PORT_NUMBER);
+
+    /**
+     * Creates a new instance.
+     */
+    private AvailablePortFinder() {
+        // Do nothing
+    }
+    
+    static {
+        int port = MIN_PORT_NUMBER;
+        ServerSocket ss = null;
+
+        while (ss == null) {
+            try {
+                ss = new ServerSocket(port);
+            } catch (Exception e) {
+                ss = null;
+                port += 200;
+            }
+        } 
+        LOCK = ss;
+        Runtime.getRuntime().addShutdownHook(new Thread() {
+            public void run() {
+                try {
+                    LOCK.close();
+                } catch (Exception ex) {
+                    //ignore
+                }
+            }
+        });
+        currentMinPort.set(port + 1);
+    }
+
+    /**
+     * Gets the next available port starting at the lowest number. This is the preferred
+     * method to use. The port return is immediately marked in use and doesn't rely on the caller actually opening
+     * the port.
+     *
+     * @throws IllegalArgumentException is thrown if the port number is out of range
+     * @throws NoSuchElementException if there are no ports available
+     * @return the available port
+     */
+    public static synchronized int getNextAvailable() {
+        int next = getNextAvailable(currentMinPort.get());
+        currentMinPort.set(next + 1);
+        return next;
+    }
+
+    /**
+     * Gets the next available port starting at a given from port.
+     *
+     * @param fromPort the from port to scan for availability
+     * @throws IllegalArgumentException is thrown if the port number is out of range
+     * @throws NoSuchElementException if there are no ports available
+     * @return the available port
+     */
+    public static synchronized int getNextAvailable(int fromPort) {
+        if (fromPort < currentMinPort.get() || fromPort > MAX_PORT_NUMBER) {
+            throw new IllegalArgumentException("From port number not in valid range: " + fromPort);
+        }
+
+        for (int i = fromPort; i <= MAX_PORT_NUMBER; i++) {
+            if (available(i)) {
+                LOG.info("getNextAvailable({}) -> {}", fromPort, i);
+                return i;
+            }
+        }
+
+        throw new NoSuchElementException("Could not find an available port above " + fromPort);
+    }
+
+    /**
+     * Checks to see if a specific port is available.
+     *
+     * @param port the port number to check for availability
+     * @return <tt>true</tt> if the port is available, or <tt>false</tt> if not
+     * @throws IllegalArgumentException is thrown if the port number is out of range
+     */
+    public static boolean available(int port) throws IllegalArgumentException {
+        if (port < currentMinPort.get() || port > MAX_PORT_NUMBER) {
+            throw new IllegalArgumentException("Invalid start currentMinPort: " + port);
+        }
+
+        ServerSocket ss = null;
+        DatagramSocket ds = null;
+        try {
+            ss = new ServerSocket(port);
+            ss.setReuseAddress(true);
+            ds = new DatagramSocket(port);
+            ds.setReuseAddress(true);
+            return true;
+        } catch (IOException e) {
+            // Do nothing
+        } finally {
+            if (ds != null) {
+                ds.close();
+            }
+
+            if (ss != null) {
+                try {
+                    ss.close();
+                } catch (IOException e) {
+                    /* should not be thrown */
+                }
+            }
+        }
+
+        return false;
+    }
+
+}


[camel] 07/07: [CAMEL-13564] Move DefaultChannel to camel-base

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit bfe9336ce5a9c2c7ba3728cda74136ddc8432aa7
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Tue May 28 23:17:24 2019 +0200

    [CAMEL-13564] Move DefaultChannel to camel-base
---
 .../src/main/java/org/apache/camel/Channel.java    |  45 ++-----
 .../camel/processor/channel/DefaultChannel.java    | 136 ++++++++-------------
 .../java/org/apache/camel/model/ModelChannel.java  |  56 ---------
 .../org/apache/camel/reifier/ProcessorReifier.java |  69 +++++++----
 .../RandomLoadBalanceJavaDSLBuilderTest.java       |   2 +-
 5 files changed, 105 insertions(+), 203 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/Channel.java b/core/camel-api/src/main/java/org/apache/camel/Channel.java
index 5ffe260..0a73529 100644
--- a/core/camel-api/src/main/java/org/apache/camel/Channel.java
+++ b/core/camel-api/src/main/java/org/apache/camel/Channel.java
@@ -29,20 +29,6 @@ import org.apache.camel.spi.RouteContext;
 public interface Channel extends AsyncProcessor, Navigate<Processor> {
 
     /**
-     * Sets the processor that the channel should route the {@link Exchange} to.
-     *
-     * @param next  the next processor
-     */
-    void setNextProcessor(Processor next);
-
-    /**
-     * Sets the {@link org.apache.camel.processor.ErrorHandler} this Channel uses.
-     *
-     * @param errorHandler the error handler
-     */
-    void setErrorHandler(Processor errorHandler);
-
-    /**
      * Gets the {@link org.apache.camel.processor.ErrorHandler} this Channel uses.
      *
      * @return the error handler, or <tt>null</tt> if no error handler is used.
@@ -50,29 +36,6 @@ public interface Channel extends AsyncProcessor, Navigate<Processor> {
     Processor getErrorHandler();
 
     /**
-     * Adds a {@link org.apache.camel.spi.InterceptStrategy} to apply each {@link Exchange} before
-     * its routed to the next {@link Processor}.
-     *
-     * @param strategy  the intercept strategy
-     */
-    void addInterceptStrategy(InterceptStrategy strategy);
-
-    /**
-     * Adds a list of {@link org.apache.camel.spi.InterceptStrategy} to apply each {@link Exchange} before
-     * its routed to the next {@link Processor}.
-     *
-     * @param strategy  list of strategies
-     */
-    void addInterceptStrategies(List<InterceptStrategy> strategy);
-
-    /**
-     * Gets the list of {@link org.apache.camel.spi.InterceptStrategy} registered to this Channel.
-     *
-     * @return list of strategies, returns an empty list if no strategies is registered.
-     */
-    List<InterceptStrategy> getInterceptStrategies();
-
-    /**
      * Gets the wrapped output that at runtime should be delegated to.
      *
      * @return the output to route the {@link Exchange} to
@@ -99,4 +62,12 @@ public interface Channel extends AsyncProcessor, Navigate<Processor> {
      * @return the route context
      */
     RouteContext getRouteContext();
+
+    /**
+     * Gets the definition of the next processor
+     *
+     * @return the processor definition
+     */
+    NamedNode getProcessorDefinition();
+
 }
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/channel/DefaultChannel.java b/core/camel-base/src/main/java/org/apache/camel/processor/channel/DefaultChannel.java
similarity index 73%
rename from core/camel-core/src/main/java/org/apache/camel/processor/channel/DefaultChannel.java
rename to core/camel-base/src/main/java/org/apache/camel/processor/channel/DefaultChannel.java
index bf77f86..d519a9b 100644
--- a/core/camel-core/src/main/java/org/apache/camel/processor/channel/DefaultChannel.java
+++ b/core/camel-base/src/main/java/org/apache/camel/processor/channel/DefaultChannel.java
@@ -26,20 +26,13 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
 import org.apache.camel.Channel;
 import org.apache.camel.Exchange;
+import org.apache.camel.NamedNode;
 import org.apache.camel.Processor;
-import org.apache.camel.model.ModelChannel;
-import org.apache.camel.model.OnCompletionDefinition;
-import org.apache.camel.model.OnExceptionDefinition;
-import org.apache.camel.model.ProcessorDefinition;
-import org.apache.camel.model.ProcessorDefinitionHelper;
-import org.apache.camel.model.RouteDefinition;
-import org.apache.camel.model.RouteDefinitionHelper;
 import org.apache.camel.processor.CamelInternalProcessor;
 import org.apache.camel.processor.WrapProcessor;
 import org.apache.camel.processor.errorhandler.RedeliveryErrorHandler;
 import org.apache.camel.processor.interceptor.BacklogDebugger;
 import org.apache.camel.processor.interceptor.BacklogTracer;
-import org.apache.camel.spi.CamelInternalProcessorAdvice;
 import org.apache.camel.spi.InterceptStrategy;
 import org.apache.camel.spi.ManagementInterceptStrategy;
 import org.apache.camel.spi.MessageHistoryFactory;
@@ -57,23 +50,18 @@ import org.apache.camel.support.service.ServiceHelper;
  * {@link Exchange} in the route graph, as we have a {@link Channel} between each and every node
  * in the graph.
  */
-public class DefaultChannel extends CamelInternalProcessor implements ModelChannel {
+public class DefaultChannel extends CamelInternalProcessor implements Channel {
 
-    private final List<InterceptStrategy> interceptors = new ArrayList<>();
     private Processor errorHandler;
     // the next processor (non wrapped)
     private Processor nextProcessor;
     // the real output to invoke that has been wrapped
     private Processor output;
-    private ProcessorDefinition<?> definition;
-    private ProcessorDefinition<?> childDefinition;
+    private NamedNode definition;
     private ManagementInterceptStrategy.InstrumentationProcessor<?> instrumentationProcessor;
     private CamelContext camelContext;
     private RouteContext routeContext;
-
-    public void setNextProcessor(Processor next) {
-        this.nextProcessor = next;
-    }
+    private boolean routeScoped = true;
 
     public Processor getOutput() {
         // the errorHandler is already decorated with interceptors
@@ -107,15 +95,11 @@ public class DefaultChannel extends CamelInternalProcessor implements ModelChann
         return nextProcessor;
     }
 
-    public boolean hasInterceptorStrategy(Class<?> type) {
-        for (InterceptStrategy strategy : interceptors) {
-            if (type.isInstance(strategy)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
+    /**
+     * Sets the {@link org.apache.camel.processor.ErrorHandler} this Channel uses.
+     *
+     * @param errorHandler the error handler
+     */
     public void setErrorHandler(Processor errorHandler) {
         this.errorHandler = errorHandler;
     }
@@ -124,26 +108,10 @@ public class DefaultChannel extends CamelInternalProcessor implements ModelChann
         return errorHandler;
     }
 
-    public void addInterceptStrategy(InterceptStrategy strategy) {
-        interceptors.add(strategy);
-    }
-
-    public void addInterceptStrategies(List<InterceptStrategy> strategies) {
-        interceptors.addAll(strategies);
-    }
-
-    public List<InterceptStrategy> getInterceptStrategies() {
-        return interceptors;
-    }
-
-    public ProcessorDefinition<?> getProcessorDefinition() {
+    public NamedNode getProcessorDefinition() {
         return definition;
     }
 
-    public void setChildDefinition(ProcessorDefinition<?> childDefinition) {
-        this.childDefinition = childDefinition;
-    }
-
     public RouteContext getRouteContext() {
         return routeContext;
     }
@@ -157,7 +125,7 @@ public class DefaultChannel extends CamelInternalProcessor implements ModelChann
 
     @Override
     protected void doStop() throws Exception {
-        if (!isContextScoped()) {
+        if (isRouteScoped()) {
             // only stop services if not context scoped (as context scoped is reused by others)
             ServiceHelper.stopService(output, errorHandler);
         }
@@ -168,68 +136,61 @@ public class DefaultChannel extends CamelInternalProcessor implements ModelChann
         ServiceHelper.stopAndShutdownServices(output, errorHandler);
     }
 
-    private boolean isContextScoped() {
-        if (definition instanceof OnExceptionDefinition) {
-            return !((OnExceptionDefinition) definition).isRouteScoped();
-        } else if (definition instanceof OnCompletionDefinition) {
-            return !((OnCompletionDefinition) definition).isRouteScoped();
-        }
-
-        return false;
+    public boolean isRouteScoped() {
+        return routeScoped;
     }
 
-    public void initChannel(ProcessorDefinition<?> outputDefinition, RouteContext routeContext) throws Exception {
+    /**
+     * Initializes the channel.
+     * If the initialized output definition contained outputs (children) then
+     * the childDefinition will be set so we can leverage fine grained tracing
+     *
+     * @param routeContext      the route context
+     * @param definition        the route definition the {@link Channel} represents
+     * @param childDefinition   the child definition
+     * @throws Exception is thrown if some error occurred
+     */
+    public void initChannel(RouteContext routeContext,
+                            NamedNode definition,
+                            NamedNode childDefinition,
+                            List<InterceptStrategy> interceptors,
+                            Processor nextProcessor,
+                            NamedNode route,
+                            boolean first,
+                            boolean routeScoped) throws Exception {
         this.routeContext = routeContext;
-        this.definition = outputDefinition;
+        this.definition = definition;
         this.camelContext = routeContext.getCamelContext();
+        this.nextProcessor = nextProcessor;
+        this.routeScoped = routeScoped;
 
-        Processor target = nextProcessor;
-        Processor next;
-
-        // init CamelContextAware as early as possible on target
-        if (target instanceof CamelContextAware) {
-            ((CamelContextAware) target).setCamelContext(camelContext);
+        // init CamelContextAware as early as possible on nextProcessor
+        if (nextProcessor instanceof CamelContextAware) {
+            ((CamelContextAware) nextProcessor).setCamelContext(camelContext);
         }
 
         // the definition to wrap should be the fine grained,
         // so if a child is set then use it, if not then its the original output used
-        ProcessorDefinition<?> targetOutputDef = childDefinition != null ? childDefinition : outputDefinition;
+        NamedNode targetOutputDef = childDefinition != null ? childDefinition : definition;
         log.debug("Initialize channel for target: '{}'", targetOutputDef);
 
-        // fix parent/child relationship. This will be the case of the routes has been
-        // defined using XML DSL or end user may have manually assembled a route from the model.
-        // Background note: parent/child relationship is assembled on-the-fly when using Java DSL (fluent builders)
-        // where as when using XML DSL (JAXB) then it fixed after, but if people are using custom interceptors
-        // then we need to fix the parent/child relationship beforehand, and thus we can do it here
-        // ideally we need the design time route -> runtime route to be a 2-phase pass (scheduled work for Camel 3.0)
-        if (childDefinition != null && outputDefinition != childDefinition) {
-            childDefinition.setParent(outputDefinition);
-        }
-
-        // force the creation of an id
-        RouteDefinitionHelper.forceAssignIds(routeContext.getCamelContext(), definition);
-
         // setup instrumentation processor for management (jmx)
         // this is later used in postInitChannel as we need to setup the error handler later as well
         ManagementInterceptStrategy managed = routeContext.getManagementInterceptStrategy();
         if (managed != null) {
-            instrumentationProcessor = managed.createProcessor(targetOutputDef, target);
+            instrumentationProcessor = managed.createProcessor(targetOutputDef, nextProcessor);
         }
 
-        // then wrap the output with the backlog and tracer (backlog first, as we do not want regular tracer to trace the backlog)
+        // then wrap the output with the backlog and tracer (backlog first,
+        // as we do not want regular tracer to trace the backlog)
         BacklogTracer tracer = getOrCreateBacklogTracer();
         camelContext.setExtension(BacklogTracer.class, tracer);
-        RouteDefinition route = ProcessorDefinitionHelper.getRoute(definition);
-        boolean first = false;
-        if (route != null && !route.getOutputs().isEmpty()) {
-            first = route.getOutputs().get(0) == definition;
-        }
         addAdvice(new BacklogTracerAdvice(tracer, targetOutputDef, route, first));
 
         // add debugger as well so we have both tracing and debugging out of the box
         BacklogDebugger debugger = getOrCreateBacklogDebugger();
         camelContext.addService(debugger);
-        addAdvice(new BacklogDebuggerAdvice(debugger, target, targetOutputDef));
+        addAdvice(new BacklogDebuggerAdvice(debugger, nextProcessor, targetOutputDef));
 
         if (routeContext.isMessageHistory()) {
             // add message history advice
@@ -242,12 +203,13 @@ public class DefaultChannel extends CamelInternalProcessor implements ModelChann
         // reverse list so the first will be wrapped last, as it would then be first being invoked
         Collections.reverse(interceptors);
         // wrap the output with the configured interceptors
+        Processor target = nextProcessor;
         for (InterceptStrategy strategy : interceptors) {
-            next = target == nextProcessor ? null : nextProcessor;
+            Processor next = target == nextProcessor ? null : nextProcessor;
             // use the fine grained definition (eg the child if available). Its always possible to get back to the parent
             Processor wrapped = strategy.wrapProcessorInInterceptors(routeContext.getCamelContext(), targetOutputDef, target, next);
             if (!(wrapped instanceof AsyncProcessor)) {
-                log.warn("Interceptor: " + strategy + " at: " + outputDefinition + " does not return an AsyncProcessor instance."
+                log.warn("Interceptor: " + strategy + " at: " + definition + " does not return an AsyncProcessor instance."
                         + " This causes the asynchronous routing engine to not work as optimal as possible."
                         + " See more details at the InterceptStrategy javadoc."
                         + " Camel will use a bridge to adapt the interceptor to the asynchronous routing engine,"
@@ -272,8 +234,12 @@ public class DefaultChannel extends CamelInternalProcessor implements ModelChann
         output = target;
     }
 
-    @Override
-    public void postInitChannel(ProcessorDefinition<?> outputDefinition, RouteContext routeContext) throws Exception {
+    /**
+     * Post initializes the channel.
+     *
+     * @throws Exception is thrown if some error occurred
+     */
+    public void postInitChannel() throws Exception {
         // if jmx was enabled for the processor then either add as advice or wrap and change the processor
         // on the error handler. See more details in the class javadoc of InstrumentationProcessor
         if (instrumentationProcessor != null) {
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/ModelChannel.java b/core/camel-core/src/main/java/org/apache/camel/model/ModelChannel.java
deleted file mode 100644
index c655f60..0000000
--- a/core/camel-core/src/main/java/org/apache/camel/model/ModelChannel.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.model;
-
-import org.apache.camel.Channel;
-import org.apache.camel.spi.RouteContext;
-
-public interface ModelChannel extends Channel {
-
-    /**
-     * Initializes the channel.
-     *
-     * @param outputDefinition  the route definition the {@link Channel} represents
-     * @param routeContext      the route context
-     * @throws Exception is thrown if some error occurred
-     */
-    void initChannel(ProcessorDefinition<?> outputDefinition, RouteContext routeContext) throws Exception;
-
-    /**
-     * Post initializes the channel.
-     *
-     * @param outputDefinition  the route definition the {@link Channel} represents
-     * @param routeContext      the route context
-     * @throws Exception is thrown if some error occurred
-     */
-    void postInitChannel(ProcessorDefinition<?> outputDefinition, RouteContext routeContext) throws Exception;
-
-    /**
-     * If the initialized output definition contained outputs (children) then we need to
-     * set the child so we can leverage fine grained tracing
-     *
-     * @param child the child
-     */
-    void setChildDefinition(ProcessorDefinition<?> child);
-    
-    /**
-     * Gets the definition of the next processor
-     *
-     * @return the processor definition
-     */
-    ProcessorDefinition<?> getProcessorDefinition();
-}
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/ProcessorReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
index f689433..9d18764 100644
--- a/core/camel-core/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
@@ -50,7 +50,6 @@ import org.apache.camel.model.LoadBalanceDefinition;
 import org.apache.camel.model.LogDefinition;
 import org.apache.camel.model.LoopDefinition;
 import org.apache.camel.model.MarshalDefinition;
-import org.apache.camel.model.ModelChannel;
 import org.apache.camel.model.MulticastDefinition;
 import org.apache.camel.model.OnCompletionDefinition;
 import org.apache.camel.model.OnExceptionDefinition;
@@ -71,6 +70,7 @@ import org.apache.camel.model.RemovePropertyDefinition;
 import org.apache.camel.model.ResequenceDefinition;
 import org.apache.camel.model.RollbackDefinition;
 import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.model.RouteDefinitionHelper;
 import org.apache.camel.model.RoutingSlipDefinition;
 import org.apache.camel.model.SagaDefinition;
 import org.apache.camel.model.SamplingDefinition;
@@ -107,7 +107,6 @@ import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
 import org.apache.camel.spi.IdAware;
 import org.apache.camel.spi.InterceptStrategy;
 import org.apache.camel.spi.LifecycleStrategy;
-import org.apache.camel.spi.NodeIdFactory;
 import org.apache.camel.spi.RouteContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -267,7 +266,7 @@ public abstract class ProcessorReifier<T extends ProcessorDefinition<?>> {
      * Wraps the child processor in whatever necessary interceptors and error handlers
      */
     public Channel wrapProcessor(RouteContext routeContext, Processor processor) throws Exception {
-        // dont double wrap
+        // don't double wrap
         if (processor instanceof Channel) {
             return (Channel) processor;
         }
@@ -280,18 +279,44 @@ public abstract class ProcessorReifier<T extends ProcessorDefinition<?>> {
 
     protected Channel wrapChannel(RouteContext routeContext, Processor processor, ProcessorDefinition<?> child, Boolean inheritErrorHandler) throws Exception {
         // put a channel in between this and each output to control the route flow logic
-        ModelChannel channel = createChannel(routeContext);
-        channel.setNextProcessor(processor);
+        DefaultChannel channel = new DefaultChannel();
 
         // add interceptor strategies to the channel must be in this order: camel context, route context, local
-        addInterceptStrategies(routeContext, channel, routeContext.getCamelContext().adapt(ExtendedCamelContext.class).getInterceptStrategies());
-        addInterceptStrategies(routeContext, channel, routeContext.getInterceptStrategies());
-        addInterceptStrategies(routeContext, channel, definition.getInterceptStrategies());
+        List<InterceptStrategy> interceptors = new ArrayList<>();
+        addInterceptStrategies(routeContext, interceptors, routeContext.getCamelContext().adapt(ExtendedCamelContext.class).getInterceptStrategies());
+        addInterceptStrategies(routeContext, interceptors, routeContext.getInterceptStrategies());
+        addInterceptStrategies(routeContext, interceptors, definition.getInterceptStrategies());
+
+        // force the creation of an id
+        RouteDefinitionHelper.forceAssignIds(routeContext.getCamelContext(), definition);
+
+        // fix parent/child relationship. This will be the case of the routes has been
+        // defined using XML DSL or end user may have manually assembled a route from the model.
+        // Background note: parent/child relationship is assembled on-the-fly when using Java DSL (fluent builders)
+        // where as when using XML DSL (JAXB) then it fixed after, but if people are using custom interceptors
+        // then we need to fix the parent/child relationship beforehand, and thus we can do it here
+        // ideally we need the design time route -> runtime route to be a 2-phase pass (scheduled work for Camel 3.0)
+        if (child != null && definition != child) {
+            child.setParent(definition);
+        }
 
         // set the child before init the channel
-        channel.setChildDefinition(child);
-        channel.initChannel(definition, routeContext);
+        RouteDefinition route = ProcessorDefinitionHelper.getRoute(definition);
+        boolean first = false;
+        if (route != null && !route.getOutputs().isEmpty()) {
+            first = route.getOutputs().get(0) == definition;
+        }
+        // set scoping
+        boolean routeScoped = true;
+        if (definition instanceof OnExceptionDefinition) {
+            routeScoped = ((OnExceptionDefinition) definition).isRouteScoped();
+        } else if (this.definition instanceof OnCompletionDefinition) {
+            routeScoped = ((OnCompletionDefinition) definition).isRouteScoped();
+        }
+        // initialize the channel
+        channel.initChannel(routeContext, definition, child, interceptors, processor, route, first, routeScoped);
 
+        boolean wrap = false;
         // set the error handler, must be done after init as we can set the error handler as first in the chain
         if (definition instanceof TryDefinition || definition instanceof CatchDefinition || definition instanceof FinallyDefinition) {
             // do not use error handler for try .. catch .. finally blocks as it will handle errors itself
@@ -310,7 +335,7 @@ public abstract class ProcessorReifier<T extends ProcessorDefinition<?>> {
             // however if inherit error handler is enabled, we need to wrap an error handler on the hystrix parent
             if (inheritErrorHandler != null && inheritErrorHandler && child == null) {
                 // only wrap the parent (not the children of the hystrix)
-                wrapChannelInErrorHandler(channel, routeContext, inheritErrorHandler);
+                wrap = true;
             } else {
                 log.trace("{} is part of HystrixCircuitBreaker so no error handler is applied", definition);
             }
@@ -321,17 +346,20 @@ public abstract class ProcessorReifier<T extends ProcessorDefinition<?>> {
             boolean isShareUnitOfWork = def.getShareUnitOfWork() != null && def.getShareUnitOfWork();
             if (isShareUnitOfWork && child == null) {
                 // only wrap the parent (not the children of the multicast)
-                wrapChannelInErrorHandler(channel, routeContext, inheritErrorHandler);
+                wrap = true;
             } else {
                 log.trace("{} is part of multicast which have special error handling so no error handler is applied", definition);
             }
         } else {
             // use error handler by default or if configured to do so
+            wrap = true;
+        }
+        if (wrap) {
             wrapChannelInErrorHandler(channel, routeContext, inheritErrorHandler);
         }
 
         // do post init at the end
-        channel.postInitChannel(definition, routeContext);
+        channel.postInitChannel();
         log.trace("{} wrapped in Channel: {}", definition, channel);
 
         return channel;
@@ -345,7 +373,7 @@ public abstract class ProcessorReifier<T extends ProcessorDefinition<?>> {
      * @param inheritErrorHandler whether to inherit error handler
      * @throws Exception can be thrown if failed to create error handler builder
      */
-    private void wrapChannelInErrorHandler(Channel channel, RouteContext routeContext, Boolean inheritErrorHandler) throws Exception {
+    private void wrapChannelInErrorHandler(DefaultChannel channel, RouteContext routeContext, Boolean inheritErrorHandler) throws Exception {
         if (inheritErrorHandler == null || inheritErrorHandler) {
             log.trace("{} is configured to inheritErrorHandler", definition);
             Processor output = channel.getOutput();
@@ -382,10 +410,10 @@ public abstract class ProcessorReifier<T extends ProcessorDefinition<?>> {
      * Adds the given list of interceptors to the channel.
      *
      * @param routeContext  the route context
-     * @param channel       the channel to add strategies
+     * @param interceptors  the list to add strategies
      * @param strategies    list of strategies to add.
      */
-    protected void addInterceptStrategies(RouteContext routeContext, Channel channel, List<InterceptStrategy> strategies) {
+    protected void addInterceptStrategies(RouteContext routeContext, List<InterceptStrategy> interceptors, List<InterceptStrategy> strategies) {
         for (InterceptStrategy strategy : strategies) {
             if (!routeContext.isHandleFault() && strategy instanceof HandleFault) {
                 // handle fault is disabled so we should not add it
@@ -393,7 +421,7 @@ public abstract class ProcessorReifier<T extends ProcessorDefinition<?>> {
             }
 
             // add strategy
-            channel.addInterceptStrategy(strategy);
+            interceptors.add(strategy);
         }
     }
 
@@ -405,13 +433,6 @@ public abstract class ProcessorReifier<T extends ProcessorDefinition<?>> {
         return Pipeline.newInstance(routeContext.getCamelContext(), list);
     }
 
-    /**
-     * Creates a new instance of the {@link Channel}.
-     */
-    protected ModelChannel createChannel(RouteContext routeContext) throws Exception {
-        return new DefaultChannel();
-    }
-
     protected Processor createOutputsProcessor(RouteContext routeContext, Collection<ProcessorDefinition<?>> outputs) throws Exception {
         // We will save list of actions to restore the outputs back to the original state.
         Runnable propertyPlaceholdersChangeReverter = ProcessorDefinitionHelper.createPropertyPlaceholdersChangeReverter();
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/RandomLoadBalanceJavaDSLBuilderTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/RandomLoadBalanceJavaDSLBuilderTest.java
index afb71c6..c3bd4b1 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/RandomLoadBalanceJavaDSLBuilderTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/RandomLoadBalanceJavaDSLBuilderTest.java
@@ -79,7 +79,7 @@ public class RandomLoadBalanceJavaDSLBuilderTest extends RandomLoadBalanceTest {
 
         if (nav instanceof DefaultChannel) {
             DefaultChannel channel = (DefaultChannel) nav;
-            ProcessorDefinition<?> def = channel.getProcessorDefinition();
+            ProcessorDefinition<?> def = (ProcessorDefinition<?>) channel.getProcessorDefinition();
             navigateDefinition(def, sb);
         }
     }


[camel] 06/07: [CAMEL-13564] Move state from ErrorHandlerBuilder to RouteContext

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 63634ae617e84f7beb997deb61ac6035c68f7af4
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Tue May 28 15:52:00 2019 +0200

    [CAMEL-13564] Move state from ErrorHandlerBuilder to RouteContext
---
 .../cdi/transaction/JtaTransactionPolicy.java      |  2 +-
 .../camel/spring/spi/SpringTransactionPolicy.java  |  2 +-
 .../java/org/apache/camel/spi/RouteContext.java    | 24 ++++++
 .../camel/impl/engine/DefaultRouteContext.java     | 22 ++++++
 .../apache/camel/builder/ErrorHandlerBuilder.java  | 23 ------
 .../camel/builder/ErrorHandlerBuilderRef.java      | 34 +-------
 .../camel/builder/ErrorHandlerBuilderSupport.java  | 50 ++----------
 .../camel/impl/AbstractModelCamelContext.java      |  5 --
 .../apache/camel/reifier/OnExceptionReifier.java   |  2 +-
 .../reifier/errorhandler/ErrorHandlerReifier.java  | 11 ++-
 .../camel/builder/ErrorHandlerBuilderRefTest.java  | 90 ----------------------
 11 files changed, 63 insertions(+), 202 deletions(-)

diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java
index e639526..eaa00c6 100644
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java
@@ -112,7 +112,7 @@ public abstract class JtaTransactionPolicy implements TransactedPolicy {
 
         // use error handlers from the configured builder
         if (builder != null) {
-            txBuilder.setErrorHandlers(routeContext, builder.getErrorHandlers(routeContext));
+            routeContext.addErrorHandlerFactoryReference(builder, txBuilder);
         }
 
         answer = createTransactionErrorHandler(routeContext, processor, txBuilder);
diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java
index 982b932..c9d3003 100644
--- a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java
+++ b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java
@@ -104,7 +104,7 @@ public class SpringTransactionPolicy implements TransactedPolicy {
             txBuilder.setSpringTransactionPolicy(this);
             if (builder != null) {
                 // use error handlers from the configured builder
-                txBuilder.setErrorHandlers(routeContext, builder.getErrorHandlers(routeContext));
+                routeContext.addErrorHandlerFactoryReference(builder, txBuilder);
             }
             answer = createTransactionErrorHandler(routeContext, processor, txBuilder);
 
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/RouteContext.java b/core/camel-api/src/main/java/org/apache/camel/spi/RouteContext.java
index d67feef..48c8967 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/RouteContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/RouteContext.java
@@ -18,6 +18,7 @@ package org.apache.camel.spi;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Endpoint;
@@ -253,4 +254,27 @@ public interface RouteContext extends RuntimeConfiguration, EndpointAware {
 
     void setOnException(String onExceptionId, Processor processor);
 
+    /**
+     * Adds error handler for the given exception type
+     *
+     * @param factory       the error handler factory
+     * @param exception     the exception to handle
+     */
+    void addErrorHandler(ErrorHandlerFactory factory, NamedNode exception);
+
+    /**
+     * Gets the error handlers
+     *
+     * @param factory       the error handler factory
+     */
+    Set<NamedNode> getErrorHandlers(ErrorHandlerFactory factory);
+
+    /**
+     * Link the error handlers from a factory to another
+     *
+     * @param source        the source factory
+     * @param target        the target factory
+     */
+    void addErrorHandlerFactoryReference(ErrorHandlerFactory source, ErrorHandlerFactory target);
+
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultRouteContext.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultRouteContext.java
index 5c362ab..14628e3 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultRouteContext.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultRouteContext.java
@@ -18,8 +18,10 @@ package org.apache.camel.impl.engine;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Endpoint;
@@ -465,4 +467,24 @@ public class DefaultRouteContext implements RouteContext {
         properties.put(key, value);
     }
 
+    private Map<ErrorHandlerFactory, Set<NamedNode>> errorHandlers = new HashMap<>();
+
+    @Override
+    public void addErrorHandler(ErrorHandlerFactory factory, NamedNode onException) {
+        getErrorHandlers(factory).add(onException);
+    }
+
+    @Override
+    public Set<NamedNode> getErrorHandlers(ErrorHandlerFactory factory) {
+        return errorHandlers.computeIfAbsent(factory, f -> new LinkedHashSet<>());
+    }
+
+    @Override
+    public void addErrorHandlerFactoryReference(ErrorHandlerFactory source, ErrorHandlerFactory target) {
+        Set<NamedNode> list = getErrorHandlers(source);
+        Set<NamedNode> previous = errorHandlers.put(target, list);
+        if (previous != null && previous != list) {
+            throw new IllegalStateException("multiple references with different handlers");
+        }
+    }
 }
diff --git a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java
index e814dba..cc0ec74 100644
--- a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java
+++ b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java
@@ -28,29 +28,6 @@ import org.apache.camel.spi.RouteContext;
 public interface ErrorHandlerBuilder extends ErrorHandlerFactory {
 
     /**
-     * Adds error handler for the given exception type
-     *
-     * @param routeContext  the route context
-     * @param exception     the exception to handle
-     */
-    void addErrorHandlers(RouteContext routeContext, OnExceptionDefinition exception);
-
-    /**
-     * Adds the error handlers for the given list of exception types
-     *
-     * @param routeContext  the route context
-     * @param exceptions    the list of exceptions to handle
-     */
-    void setErrorHandlers(RouteContext routeContext, List<OnExceptionDefinition> exceptions);
-
-    /**
-     * Gets the error handlers
-     *
-     * @param routeContext  the route context
-     */
-    List<OnExceptionDefinition> getErrorHandlers(RouteContext routeContext);
-
-    /**
      * Whether this error handler supports transacted exchanges.
      */
     boolean supportTransacted();
diff --git a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java
index 2d854e3..ebc60e9 100644
--- a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java
+++ b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java
@@ -32,36 +32,14 @@ import org.apache.camel.util.ObjectHelper;
  */
 public class ErrorHandlerBuilderRef extends ErrorHandlerBuilderSupport {
     private final String ref;
-    private final Map<RouteContext, ErrorHandlerBuilder> handlers = new HashMap<>();
     private boolean supportTransacted;
 
     public ErrorHandlerBuilderRef(String ref) {
         this.ref = ref;
     }
 
-    @Override
-    public void addErrorHandlers(RouteContext routeContext, OnExceptionDefinition exception) {
-        ErrorHandlerBuilder handler = handlers.get(routeContext);
-        if (handler != null) {
-            handler.addErrorHandlers(routeContext, exception);
-        }
-        super.addErrorHandlers(routeContext, exception);
-    }
-    
-    @Override
-    public boolean removeOnExceptionList(String id) {
-        for (RouteContext routeContext : handlers.keySet()) {
-            if (routeContext.getRouteId().equals(id)) {
-                handlers.remove(routeContext);
-                break;
-            }
-        }
-        return super.removeOnExceptionList(id);
-    }
-    
-
     public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception {
-        ErrorHandlerFactory handler = handlers.computeIfAbsent(routeContext, this::createErrorHandler);
+        ErrorHandlerFactory handler = lookupErrorHandler(routeContext);
         return ErrorHandlerReifier.reifier(handler).createErrorHandler(routeContext, processor);
     }
 
@@ -88,19 +66,15 @@ public class ErrorHandlerBuilderRef extends ErrorHandlerBuilderSupport {
         return ref;
     }
 
-    private ErrorHandlerBuilder createErrorHandler(RouteContext routeContext) {
+    private ErrorHandlerBuilder lookupErrorHandler(RouteContext routeContext) {
         ErrorHandlerBuilder handler = (ErrorHandlerBuilder) ErrorHandlerReifier.lookupErrorHandlerFactory(routeContext, getRef());
         ObjectHelper.notNull(handler, "error handler '" + ref + "'");
 
         // configure if the handler support transacted
         supportTransacted = handler.supportTransacted();
 
-        List<OnExceptionDefinition> list = getErrorHandlers(routeContext);
-        if (list != null) {
-            for (OnExceptionDefinition exceptionType : list) {
-                handler.addErrorHandlers(routeContext, exceptionType);
-            }
-        }
+        routeContext.addErrorHandlerFactoryReference(this, handler);
+
         return handler;
     }
 
diff --git a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java
index 8e60a61..5058439 100644
--- a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java
+++ b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java
@@ -17,10 +17,10 @@
 package org.apache.camel.builder;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
+import java.util.Set;
 
+import org.apache.camel.NamedNode;
 import org.apache.camel.Predicate;
 import org.apache.camel.Processor;
 import org.apache.camel.RuntimeCamelException;
@@ -42,21 +42,9 @@ import org.apache.camel.util.ObjectHelper;
  * Base class for builders of error handling.
  */
 public abstract class ErrorHandlerBuilderSupport implements ErrorHandlerBuilder {
-    private Map<RouteContext, List<OnExceptionDefinition>> onExceptions = new HashMap<>();
     private ExceptionPolicyStrategy exceptionPolicyStrategy;
 
-    public void addErrorHandlers(RouteContext routeContext, OnExceptionDefinition exception) {
-        // only add if we not already have it
-        List<OnExceptionDefinition> list = onExceptions.computeIfAbsent(routeContext, rc -> new ArrayList<>());
-        if (!list.contains(exception)) {
-            list.add(exception);
-        }
-    }
-
     protected void cloneBuilder(ErrorHandlerBuilderSupport other) {
-        if (!onExceptions.isEmpty()) {
-            other.onExceptions.putAll(onExceptions);
-        }
         other.exceptionPolicyStrategy = exceptionPolicyStrategy;
     }
 
@@ -70,11 +58,9 @@ public abstract class ErrorHandlerBuilderSupport implements ErrorHandlerBuilder
         if (handler instanceof ErrorHandlerSupport) {
             ErrorHandlerSupport handlerSupport = (ErrorHandlerSupport) handler;
 
-            List<OnExceptionDefinition> list = onExceptions.get(routeContext);
-            if (list != null) {
-                for (OnExceptionDefinition exception : list) {
-                    addExceptionPolicy(handlerSupport, routeContext, exception);
-                }
+            Set<NamedNode> list = routeContext.getErrorHandlers(this);
+            for (NamedNode exception : list) {
+                addExceptionPolicy(handlerSupport, routeContext, (OnExceptionDefinition) exception);
             }
         }
         if (handler instanceof RedeliveryErrorHandler) {
@@ -132,14 +118,6 @@ public abstract class ErrorHandlerBuilderSupport implements ErrorHandlerBuilder
         return answer;
     }
 
-    public List<OnExceptionDefinition> getErrorHandlers(RouteContext routeContext) {
-        return onExceptions.get(routeContext);
-    }
-
-    public void setErrorHandlers(RouteContext routeContext, List<OnExceptionDefinition> exceptions) {
-        this.onExceptions.put(routeContext, exceptions);
-    }
-
     /**
      * Sets the exception policy to use
      */
@@ -166,22 +144,4 @@ public abstract class ErrorHandlerBuilderSupport implements ErrorHandlerBuilder
         this.exceptionPolicyStrategy = exceptionPolicyStrategy;
     }
     
-    /**
-     * Remove the OnExceptionList by look up the route id from the ErrorHandlerBuilder internal map
-     * @param id the route id
-     * @return true if the route context is found and removed
-     */
-    public boolean removeOnExceptionList(String id) {
-        for (RouteContext routeContext : onExceptions.keySet()) {
-            if (routeContext.getRouteId().equals(id)) {
-                onExceptions.remove(routeContext);
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public Map<RouteContext, List<OnExceptionDefinition>> getOnExceptions() {
-        return onExceptions;
-    }
 }
diff --git a/core/camel-core/src/main/java/org/apache/camel/impl/AbstractModelCamelContext.java b/core/camel-core/src/main/java/org/apache/camel/impl/AbstractModelCamelContext.java
index 449a2fd..10e4826 100644
--- a/core/camel-core/src/main/java/org/apache/camel/impl/AbstractModelCamelContext.java
+++ b/core/camel-core/src/main/java/org/apache/camel/impl/AbstractModelCamelContext.java
@@ -287,11 +287,6 @@ public abstract class AbstractModelCamelContext extends AbstractCamelContext imp
     }
 
     protected synchronized void shutdownRouteService(BaseRouteService routeService) throws Exception {
-        // remove the route from ErrorHandlerBuilder if possible
-        if (getErrorHandlerFactory() instanceof ErrorHandlerBuilderSupport) {
-            ErrorHandlerBuilderSupport builder = (ErrorHandlerBuilderSupport) getErrorHandlerFactory();
-            builder.removeOnExceptionList(routeService.getId());
-        }
         if (routeService instanceof RouteService) {
             model.getRouteDefinitions().remove(((RouteService) routeService).getRouteDefinition());
         }
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/OnExceptionReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/OnExceptionReifier.java
index 98d19f8..eb5d3b9 100644
--- a/core/camel-core/src/main/java/org/apache/camel/reifier/OnExceptionReifier.java
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/OnExceptionReifier.java
@@ -73,7 +73,7 @@ class OnExceptionReifier extends ProcessorReifier<OnExceptionDefinition> {
         // lookup the error handler builder
         ErrorHandlerBuilder builder = (ErrorHandlerBuilder) routeContext.getErrorHandlerFactory();
         // and add this as error handlers
-        builder.addErrorHandlers(routeContext, definition);
+        routeContext.addErrorHandler(builder, definition);
     }
 
     @Override
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java
index a7649ca..21c9d59 100644
--- a/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java
@@ -19,11 +19,13 @@ package org.apache.camel.reifier.errorhandler;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.function.Function;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ErrorHandlerFactory;
 import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.NamedNode;
 import org.apache.camel.Processor;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.builder.DeadLetterChannelBuilder;
@@ -193,7 +195,7 @@ public abstract class ErrorHandlerReifier<T extends ErrorHandlerBuilderSupport>
                 }
                 // inherit the error handlers from the other as they are to be shared
                 // this is needed by camel-spring when none error handler has been explicit configured
-                ((ErrorHandlerBuilderSupport) answer).setErrorHandlers(routeContext, other.getErrorHandlers(routeContext));
+                routeContext.addErrorHandlerFactoryReference(other, answer);
             }
         } else {
             // use specific configured error handler
@@ -250,11 +252,8 @@ public abstract class ErrorHandlerReifier<T extends ErrorHandlerBuilderSupport>
         if (handler instanceof ErrorHandlerSupport) {
             ErrorHandlerSupport handlerSupport = (ErrorHandlerSupport) handler;
 
-            List<OnExceptionDefinition> list = definition.getOnExceptions().get(routeContext);
-            if (list != null) {
-                for (OnExceptionDefinition exception : list) {
-                    ErrorHandlerBuilderSupport.addExceptionPolicy(handlerSupport, routeContext, exception);
-                }
+            for (NamedNode exception : routeContext.getErrorHandlers(definition)) {
+                ErrorHandlerBuilderSupport.addExceptionPolicy(handlerSupport, routeContext, (OnExceptionDefinition) exception);
             }
         }
         if (handler instanceof RedeliveryErrorHandler) {
diff --git a/core/camel-core/src/test/java/org/apache/camel/builder/ErrorHandlerBuilderRefTest.java b/core/camel-core/src/test/java/org/apache/camel/builder/ErrorHandlerBuilderRefTest.java
deleted file mode 100644
index 2479629..0000000
--- a/core/camel-core/src/test/java/org/apache/camel/builder/ErrorHandlerBuilderRefTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.lang.reflect.Field;
-import java.util.Map;
-import java.util.UUID;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.ContextTestSupport;
-import org.apache.camel.ExtendedCamelContext;
-import org.apache.camel.impl.JndiRegistry;
-import org.junit.Test;
-
-public class ErrorHandlerBuilderRefTest extends ContextTestSupport {
-    ErrorHandlerBuilderRef errorHandlerBuilderRef = new ErrorHandlerBuilderRef("ref");
-    
-    @Override
-    public boolean isUseRouteBuilder() {
-        return true;
-    }
-    
-    @Override
-    protected JndiRegistry createRegistry() throws Exception {
-        JndiRegistry registry = super.createRegistry();
-        registry.bind("ref", new DefaultErrorHandlerBuilder());
-        return registry;
-    }
-    
-    @Override
-    protected CamelContext createCamelContext() throws Exception {
-        CamelContext context = super.createCamelContext();
-        context.adapt(ExtendedCamelContext.class).setErrorHandlerFactory(errorHandlerBuilderRef);
-        return context;
-    }
-    
-    @Test
-    public void testErrorHandlerBuilderRef() throws Exception {
-        String uuid = UUID.randomUUID().toString();
-        context.addRoutes(new TempRouteBuilder(uuid));
-        checkObjectSize(2);
-        context.getRouteController().stopRoute(uuid);
-        context.removeRoute(uuid);
-        checkObjectSize(1);
-    }
-    
-    private void checkObjectSize(int size) throws Exception {
-        assertEquals("Get a wrong size of Route", size, context.getRoutes().size());
-        Field field = ErrorHandlerBuilderRef.class.getDeclaredField("handlers");
-        field.setAccessible(true);
-        assertEquals("Get a wrong size of ErrorHandler", size, ((Map<?, ?>) field.get(errorHandlerBuilderRef)).size());
-    }
-    
-    private static class TempRouteBuilder extends RouteBuilder {
-
-        final String routeId;
-
-        TempRouteBuilder(String routeId) {
-            this.routeId = routeId;
-        }
-
-        @Override
-        public void configure() throws Exception {
-            from("direct:foo").routeId(routeId).to("mock:foo");
-        }
-    }
-    
-    protected RouteBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            public void configure() {
-                from("direct:start").to("mock:result");
-            }
-        };
-    }
-
-}


[camel] 04/07: [CAMEL-13564] Remove redundant error handler configuration

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit c12994378526496eb7f3e61a33d588dd76abc41b
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Tue May 28 11:19:49 2019 +0200

    [CAMEL-13564] Remove redundant error handler configuration
---
 .../cdi/transaction/JtaTransactionPolicy.java      |  3 ---
 .../camel/spring/spi/SpringTransactionPolicy.java  |  6 ------
 .../apache/camel/builder/ErrorHandlerBuilder.java  | 23 ----------------------
 .../camel/builder/ErrorHandlerBuilderSupport.java  | 15 ++++++++++++++
 .../apache/camel/reifier/DynamicRouterReifier.java |  1 -
 5 files changed, 15 insertions(+), 33 deletions(-)

diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java
index e0e6c46..e639526 100644
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java
@@ -116,9 +116,6 @@ public abstract class JtaTransactionPolicy implements TransactedPolicy {
         }
 
         answer = createTransactionErrorHandler(routeContext, processor, txBuilder);
-        answer.setExceptionPolicy(txBuilder.getExceptionPolicyStrategy());
-        // configure our answer based on the existing error handler
-        txBuilder.configure(routeContext, answer);
 
         // set the route to use our transacted error handler builder
         route.setErrorHandlerFactory(txBuilder);
diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java
index a35f9b2..982b932 100644
--- a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java
+++ b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java
@@ -90,9 +90,6 @@ public class SpringTransactionPolicy implements TransactedPolicy {
             // already a TX error handler then we are good to go
             LOG.debug("The ErrorHandlerBuilder configured is already a TransactionErrorHandlerBuilder: {}", builder);
             answer = createTransactionErrorHandler(routeContext, processor, builder);
-            answer.setExceptionPolicy(builder.getExceptionPolicyStrategy());
-            // configure our answer based on the existing error handler
-            builder.configure(routeContext, answer);
         } else {
             // no transaction error handler builder configure so create a temporary one as we got all
             // the needed information form the configured builder anyway this allow us to use transacted
@@ -110,9 +107,6 @@ public class SpringTransactionPolicy implements TransactedPolicy {
                 txBuilder.setErrorHandlers(routeContext, builder.getErrorHandlers(routeContext));
             }
             answer = createTransactionErrorHandler(routeContext, processor, txBuilder);
-            answer.setExceptionPolicy(txBuilder.getExceptionPolicyStrategy());
-            // configure our answer based on the existing error handler
-            txBuilder.configure(routeContext, answer);
 
             // set the route to use our transacted error handler builder
             route.setErrorHandlerFactory(txBuilder);
diff --git a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java
index e4c87a8..e814dba 100644
--- a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java
+++ b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilder.java
@@ -20,8 +20,6 @@ import java.util.List;
 
 import org.apache.camel.ErrorHandlerFactory;
 import org.apache.camel.model.OnExceptionDefinition;
-import org.apache.camel.processor.ErrorHandler;
-import org.apache.camel.processor.errorhandler.ExceptionPolicyStrategy;
 import org.apache.camel.spi.RouteContext;
 
 /**
@@ -53,32 +51,11 @@ public interface ErrorHandlerBuilder extends ErrorHandlerFactory {
     List<OnExceptionDefinition> getErrorHandlers(RouteContext routeContext);
 
     /**
-     * Gets the exception policy strategy
-     */
-    ExceptionPolicyStrategy getExceptionPolicyStrategy();
-
-    /**
-     * Sets the exception policy strategy to use for resolving the {@link org.apache.camel.model.OnExceptionDefinition}
-     * to use for a given thrown exception
-     *
-     * @param exceptionPolicyStrategy  the exception policy strategy
-     */
-    void setExceptionPolicyStrategy(ExceptionPolicyStrategy exceptionPolicyStrategy);
-
-    /**
      * Whether this error handler supports transacted exchanges.
      */
     boolean supportTransacted();
 
     /**
-     * Configures the other error handler based on this error handler.
-     *
-     * @param routeContext the route context
-     * @param handler the other error handler
-     */
-    void configure(RouteContext routeContext, ErrorHandler handler);
-
-    /**
      * Clones this builder so each {@link RouteBuilder} has its private builder
      * to use, to avoid changes from one {@link RouteBuilder} to influence the
      * others.
diff --git a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java
index a0e86e2..8e60a61 100644
--- a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java
+++ b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java
@@ -60,6 +60,12 @@ public abstract class ErrorHandlerBuilderSupport implements ErrorHandlerBuilder
         other.exceptionPolicyStrategy = exceptionPolicyStrategy;
     }
 
+    /**
+     * Configures the other error handler based on this error handler.
+     *
+     * @param routeContext the route context
+     * @param handler the other error handler
+     */
     public void configure(RouteContext routeContext, ErrorHandler handler) {
         if (handler instanceof ErrorHandlerSupport) {
             ErrorHandlerSupport handlerSupport = (ErrorHandlerSupport) handler;
@@ -142,10 +148,19 @@ public abstract class ErrorHandlerBuilderSupport implements ErrorHandlerBuilder
         return this;
     }
 
+    /**
+     * Gets the exception policy strategy
+     */
     public ExceptionPolicyStrategy getExceptionPolicyStrategy() {
         return exceptionPolicyStrategy;
     }
 
+    /**
+     * Sets the exception policy strategy to use for resolving the {@link org.apache.camel.model.OnExceptionDefinition}
+     * to use for a given thrown exception
+     *
+     * @param exceptionPolicyStrategy  the exception policy strategy
+     */
     public void setExceptionPolicyStrategy(ExceptionPolicyStrategy exceptionPolicyStrategy) {
         ObjectHelper.notNull(exceptionPolicyStrategy, "ExceptionPolicyStrategy");
         this.exceptionPolicyStrategy = exceptionPolicyStrategy;
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java
index 557e291..a0d8acf 100644
--- a/core/camel-core/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java
@@ -22,7 +22,6 @@ import org.apache.camel.Expression;
 import org.apache.camel.Processor;
 import org.apache.camel.model.DynamicRouterDefinition;
 import org.apache.camel.model.ProcessorDefinition;
-import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.processor.DynamicRouter;
 import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
 import org.apache.camel.spi.RouteContext;


[camel] 01/07: [CAMEL-13564] Split exception/error handling model from runtime

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 552ee0cc3eb736de8b360eb910d8571df6b558b0
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Thu May 23 17:46:33 2019 +0200

    [CAMEL-13564] Split exception/error handling model from runtime
    
    Remaining things:
      - MulticastProcessor.createErrorHandler
      - ErrorHandlerRefReifier.createErrorHandler
      - move state from ErrorHandlerBuilderSupport and ErrorHandlerBuilderRef to RouteContext
---
 components/camel-blueprint/pom.xml                 |   4 +
 .../blueprint/CamelErrorHandlerFactoryBean.java    |   2 +-
 .../cdi/transaction/JtaTransactionPolicy.java      |   3 +-
 .../camel/spring/spi/SpringTransactionPolicy.java  |   3 +-
 .../spring/spi/TransactionErrorHandlerBuilder.java |   5 +
 .../spring/spi/TransactionErrorHandlerReifier.java |  89 ++++++++++++++++
 .../camel/builder/DefaultErrorHandlerBuilder.java  |   8 ++
 .../camel/builder/ErrorHandlerBuilderRef.java      |   3 +-
 .../camel/builder/ErrorHandlerBuilderSupport.java  |  62 ++++++++++-
 .../errorhandler/ErrorHandlerSupport.java          |  59 ++---------
 .../errorhandler/RedeliveryErrorHandler.java       |  30 ++----
 .../DefaultExceptionPolicyStrategy.java            |  59 +++++------
 .../processor/exceptionpolicy/ExceptionPolicy.java |  85 +++++++++++++++
 .../exceptionpolicy/ExceptionPolicyKey.java        |   8 +-
 .../exceptionpolicy/ExceptionPolicyStrategy.java   |   9 +-
 .../apache/camel/reifier/DynamicRouterReifier.java |   3 +-
 .../apache/camel/reifier/OnExceptionReifier.java   |   1 +
 .../org/apache/camel/reifier/ProcessorReifier.java |   3 +-
 .../apache/camel/reifier/RoutingSlipReifier.java   |   3 +-
 .../errorhandler/DeadLetterChannelReifier.java     |  48 +++++++++
 .../errorhandler/DefaultErrorHandlerReifier.java   |  69 ++++++++++++
 .../errorhandler/ErrorHandlerRefReifier.java       |  19 ++++
 .../{ => errorhandler}/ErrorHandlerReifier.java    | 118 +++++++++++++++++++--
 .../errorhandler/NoErrorHandlerReifier.java        |  41 +++++++
 .../ValidatorEndpointClearCachedSchemaTest.java    |   5 +
 .../errorhandler/ErrorHandlerSupportTest.java      |  13 +--
 .../CustomExceptionPolicyStrategyTest.java         |   3 +-
 .../DefaultExceptionPolicyStrategyTest.java        |  48 ++++-----
 28 files changed, 641 insertions(+), 162 deletions(-)

diff --git a/components/camel-blueprint/pom.xml b/components/camel-blueprint/pom.xml
index a7880bf..3179463 100644
--- a/components/camel-blueprint/pom.xml
+++ b/components/camel-blueprint/pom.xml
@@ -52,6 +52,10 @@
             <artifactId>camel-core-osgi</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-core</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>osgi.core</artifactId>
             <scope>provided</scope>
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 de4aa2f..38199df 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
@@ -31,7 +31,7 @@ import org.apache.camel.builder.ErrorHandlerBuilder;
 import org.apache.camel.core.xml.AbstractCamelFactoryBean;
 import org.apache.camel.model.RedeliveryPolicyDefinition;
 import org.apache.camel.processor.errorhandler.RedeliveryPolicy;
-import org.apache.camel.reifier.ErrorHandlerReifier;
+import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
 import org.osgi.service.blueprint.container.BlueprintContainer;
 
 @XmlRootElement(name = "errorHandler")
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java
index e674b3d..d2dd5ebe 100644
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/transaction/JtaTransactionPolicy.java
@@ -26,6 +26,7 @@ import org.apache.camel.builder.ErrorHandlerBuilder;
 import org.apache.camel.builder.ErrorHandlerBuilderRef;
 import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.spi.TransactedPolicy;
 import org.slf4j.Logger;
@@ -130,7 +131,7 @@ public abstract class JtaTransactionPolicy implements TransactedPolicy {
             ErrorHandlerBuilder builder) {
         JtaTransactionErrorHandler answer;
         try {
-            answer = (JtaTransactionErrorHandler) builder.createErrorHandler(routeContext, processor);
+            answer = (JtaTransactionErrorHandler) ErrorHandlerReifier.reifier(builder).createErrorHandler(routeContext, processor);
         } catch (Exception e) {
             throw RuntimeCamelException.wrapRuntimeCamelException(e);
         }
diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java
index 362160e..a67b4f3 100644
--- a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java
+++ b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringTransactionPolicy.java
@@ -22,6 +22,7 @@ import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.builder.ErrorHandlerBuilder;
 import org.apache.camel.builder.ErrorHandlerBuilderRef;
 import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.spi.TransactedPolicy;
 import org.apache.camel.spi.annotations.JdkService;
@@ -124,7 +125,7 @@ public class SpringTransactionPolicy implements TransactedPolicy {
     protected TransactionErrorHandler createTransactionErrorHandler(RouteContext routeContext, Processor processor, ErrorHandlerBuilder builder) {
         TransactionErrorHandler answer;
         try {
-            answer = (TransactionErrorHandler) builder.createErrorHandler(routeContext, processor);
+            answer = (TransactionErrorHandler) ErrorHandlerReifier.reifier(builder).createErrorHandler(routeContext, processor);
         } catch (Exception e) {
             throw RuntimeCamelException.wrapRuntimeCamelException(e);
         }
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 361f02c..8e2c918 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
@@ -21,6 +21,7 @@ import java.util.Map;
 import org.apache.camel.LoggingLevel;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.DefaultErrorHandlerBuilder;
+import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
 import org.apache.camel.spi.CamelLogger;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.spi.TransactedPolicy;
@@ -35,6 +36,10 @@ import org.springframework.transaction.support.TransactionTemplate;
  */
 public class TransactionErrorHandlerBuilder extends DefaultErrorHandlerBuilder {
 
+    static {
+        ErrorHandlerReifier.registerReifier(TransactionErrorHandlerBuilder.class, TransactionErrorHandlerReifier::new);
+    }
+
     private static final Logger LOG = LoggerFactory.getLogger(TransactionErrorHandlerBuilder.class);
     private static final String PROPAGATION_REQUIRED = "PROPAGATION_REQUIRED";
     private TransactionTemplate transactionTemplate;
diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandlerReifier.java b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandlerReifier.java
new file mode 100644
index 0000000..d50c49c
--- /dev/null
+++ b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/TransactionErrorHandlerReifier.java
@@ -0,0 +1,89 @@
+package org.apache.camel.spring.spi;
+
+import java.util.Map;
+
+import org.apache.camel.ErrorHandlerFactory;
+import org.apache.camel.Processor;
+import org.apache.camel.reifier.errorhandler.DefaultErrorHandlerReifier;
+import org.apache.camel.spi.RouteContext;
+import org.apache.camel.spi.TransactedPolicy;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import static org.apache.camel.model.TransactedDefinition.PROPAGATION_REQUIRED;
+
+public class TransactionErrorHandlerReifier extends DefaultErrorHandlerReifier<TransactionErrorHandlerBuilder> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(TransactionErrorHandlerReifier.class);
+
+    public TransactionErrorHandlerReifier(ErrorHandlerFactory definition) {
+        super(definition);
+    }
+
+    public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception {
+        TransactionTemplate transactionTemplate = definition.getTransactionTemplate();
+        if (transactionTemplate == null) {
+            // lookup in context if no transaction template has been configured
+            LOG.debug("No TransactionTemplate configured on TransactionErrorHandlerBuilder. Will try find it in the registry.");
+
+            Map<String, TransactedPolicy> mapPolicy = routeContext.lookupByType(TransactedPolicy.class);
+            if (mapPolicy != null && mapPolicy.size() == 1) {
+                TransactedPolicy policy = mapPolicy.values().iterator().next();
+                if (policy instanceof SpringTransactionPolicy) {
+                    transactionTemplate = ((SpringTransactionPolicy) policy).getTransactionTemplate();
+                }
+            }
+
+            if (transactionTemplate == null) {
+                TransactedPolicy policy = routeContext.lookup(PROPAGATION_REQUIRED, TransactedPolicy.class);
+                if (policy instanceof SpringTransactionPolicy) {
+                    transactionTemplate = ((SpringTransactionPolicy) policy).getTransactionTemplate();
+                }
+            }
+
+            if (transactionTemplate == null) {
+                Map<String, TransactionTemplate> mapTemplate = routeContext.lookupByType(TransactionTemplate.class);
+                if (mapTemplate == null || mapTemplate.isEmpty()) {
+                    LOG.trace("No TransactionTemplate found in registry.");
+                } else if (mapTemplate.size() == 1) {
+                    transactionTemplate = mapTemplate.values().iterator().next();
+                } else {
+                    LOG.debug("Found {} TransactionTemplate in registry. Cannot determine which one to use. "
+                            + "Please configure a TransactionTemplate on the TransactionErrorHandlerBuilder", mapTemplate.size());
+                }
+            }
+
+            if (transactionTemplate == null) {
+                Map<String, PlatformTransactionManager> mapManager = routeContext.lookupByType(PlatformTransactionManager.class);
+                if (mapManager == null || mapManager.isEmpty()) {
+                    LOG.trace("No PlatformTransactionManager found in registry.");
+                } else if (mapManager.size() == 1) {
+                    transactionTemplate = new TransactionTemplate(mapManager.values().iterator().next());
+                } else {
+                    LOG.debug("Found {} PlatformTransactionManager in registry. Cannot determine which one to use for TransactionTemplate. "
+                            + "Please configure a TransactionTemplate on the TransactionErrorHandlerBuilder", mapManager.size());
+                }
+            }
+
+            if (transactionTemplate != null) {
+                LOG.debug("Found TransactionTemplate in registry to use: {}", transactionTemplate);
+            }
+        }
+
+        ObjectHelper.notNull(transactionTemplate, "transactionTemplate", this);
+
+        TransactionErrorHandler answer = new TransactionErrorHandler(routeContext.getCamelContext(), processor,
+                definition.getLogger(), definition.getOnRedelivery(),
+                definition.getRedeliveryPolicy(), definition.getExceptionPolicyStrategy(), transactionTemplate,
+                definition.getRetryWhilePolicy(routeContext.getCamelContext()),
+                getExecutorService(routeContext.getCamelContext()),
+                definition.getRollbackLoggingLevel(), definition.getOnExceptionOccurred());
+        // configure error handler before we can use it
+        configure(routeContext, answer);
+        return answer;
+    }
+
+}
diff --git a/core/camel-core/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java b/core/camel-core/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java
index cd6b982..768f63c 100644
--- a/core/camel-core/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java
+++ b/core/camel-core/src/main/java/org/apache/camel/builder/DefaultErrorHandlerBuilder.java
@@ -521,6 +521,14 @@ public class DefaultErrorHandlerBuilder extends ErrorHandlerBuilderSupport {
         this.asyncDelayedRedelivery = asyncDelayedRedelivery;
     }
 
+    public ScheduledExecutorService getExecutorService() {
+        return executorService;
+    }
+
+    public void setExecutorService(ScheduledExecutorService executorService) {
+        this.executorService = executorService;
+    }
+
     public String getExecutorServiceRef() {
         return executorServiceRef;
     }
diff --git a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java
index d292f0e..27e4c42 100644
--- a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java
+++ b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderRef.java
@@ -26,6 +26,7 @@ import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.Processor;
 import org.apache.camel.model.OnExceptionDefinition;
 import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.util.ObjectHelper;
 
@@ -65,7 +66,7 @@ public class ErrorHandlerBuilderRef extends ErrorHandlerBuilderSupport {
 
     public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception {
         ErrorHandlerFactory handler = handlers.computeIfAbsent(routeContext, this::createErrorHandler);
-        return handler.createErrorHandler(routeContext, processor);
+        return ErrorHandlerReifier.reifier(handler).createErrorHandler(routeContext, processor);
     }
 
     public boolean supportTransacted() {
diff --git a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java
index bd951a8..217351d 100644
--- a/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java
+++ b/core/camel-core/src/main/java/org/apache/camel/builder/ErrorHandlerBuilderSupport.java
@@ -21,11 +21,19 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.camel.Predicate;
+import org.apache.camel.Processor;
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.model.OnExceptionDefinition;
+import org.apache.camel.model.ProcessorDefinitionHelper;
+import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.processor.ErrorHandler;
 import org.apache.camel.processor.errorhandler.ErrorHandlerSupport;
 import org.apache.camel.processor.errorhandler.RedeliveryErrorHandler;
+import org.apache.camel.processor.exceptionpolicy.ExceptionPolicy;
+import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyKey;
 import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
+import org.apache.camel.spi.ClassResolver;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.util.ObjectHelper;
 
@@ -46,8 +54,7 @@ public abstract class ErrorHandlerBuilderSupport implements ErrorHandlerBuilder
 
     protected void cloneBuilder(ErrorHandlerBuilderSupport other) {
         if (!onExceptions.isEmpty()) {
-            Map<RouteContext, List<OnExceptionDefinition>> copy = new HashMap<>(onExceptions);
-            other.onExceptions = copy;
+            other.onExceptions.putAll(onExceptions);
         }
         other.exceptionPolicyStrategy = exceptionPolicyStrategy;
     }
@@ -59,7 +66,7 @@ public abstract class ErrorHandlerBuilderSupport implements ErrorHandlerBuilder
             List<OnExceptionDefinition> list = onExceptions.get(routeContext);
             if (list != null) {
                 for (OnExceptionDefinition exception : list) {
-                    handlerSupport.addExceptionPolicy(routeContext, exception);
+                    addExceptionPolicy(handlerSupport, routeContext, exception);
                 }
             }
         }
@@ -72,6 +79,52 @@ public abstract class ErrorHandlerBuilderSupport implements ErrorHandlerBuilder
         }
     }
 
+    public static void addExceptionPolicy(ErrorHandlerSupport handlerSupport, RouteContext routeContext, OnExceptionDefinition exceptionType) {
+        if (routeContext != null) {
+            // add error handler as child service so they get lifecycle handled
+            Processor errorHandler = routeContext.getOnException(exceptionType.getId());
+            handlerSupport.addErrorHandler(errorHandler);
+
+            // load exception classes
+            List<Class<? extends Throwable>> list;
+            if (exceptionType.getExceptions() != null && !exceptionType.getExceptions().isEmpty()) {
+                list = createExceptionClasses(exceptionType, routeContext.getCamelContext().getClassResolver());
+                for (Class<? extends Throwable> clazz : list) {
+                    String routeId = null;
+                    // only get the route id, if the exception type is route scoped
+                    if (exceptionType.isRouteScoped()) {
+                        RouteDefinition route = ProcessorDefinitionHelper.getRoute(exceptionType);
+                        if (route != null) {
+                            routeId = route.getId();
+                        }
+                    }
+                    Predicate when = exceptionType.getOnWhen() != null ? exceptionType.getOnWhen().getExpression() : null;
+                    ExceptionPolicyKey key = new ExceptionPolicyKey(routeId, clazz, when);
+                    ExceptionPolicy policy = toExceptionPolicy(exceptionType);
+                    handlerSupport.addExceptionPolicy(key, policy);
+                }
+            }
+        }
+    }
+
+    protected static ExceptionPolicy toExceptionPolicy(OnExceptionDefinition exceptionType) {
+        return new ExceptionPolicy(exceptionType);
+    }
+
+    protected static List<Class<? extends Throwable>> createExceptionClasses(OnExceptionDefinition exceptionType, ClassResolver resolver) {
+        List<String> list = exceptionType.getExceptions();
+        List<Class<? extends Throwable>> answer = new ArrayList<>(list.size());
+        for (String name : list) {
+            try {
+                Class<? extends Throwable> type = resolver.resolveMandatoryClass(name, Throwable.class);
+                answer.add(type);
+            } catch (ClassNotFoundException e) {
+                throw RuntimeCamelException.wrapRuntimeCamelException(e);
+            }
+        }
+        return answer;
+    }
+
     public List<OnExceptionDefinition> getErrorHandlers(RouteContext routeContext) {
         return onExceptions.get(routeContext);
     }
@@ -112,4 +165,7 @@ public abstract class ErrorHandlerBuilderSupport implements ErrorHandlerBuilder
         return false;
     }
 
+    public Map<RouteContext, List<OnExceptionDefinition>> getOnExceptions() {
+        return onExceptions;
+    }
 }
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupport.java b/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupport.java
index dfa1ebc..5f8a45f 100644
--- a/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupport.java
+++ b/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupport.java
@@ -16,23 +16,16 @@
  */
 package org.apache.camel.processor.errorhandler;
 
-import java.util.ArrayList;
 import java.util.LinkedHashMap;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
-import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.model.OnExceptionDefinition;
-import org.apache.camel.model.ProcessorDefinitionHelper;
-import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.processor.ErrorHandler;
 import org.apache.camel.processor.exceptionpolicy.DefaultExceptionPolicyStrategy;
+import org.apache.camel.processor.exceptionpolicy.ExceptionPolicy;
 import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyKey;
 import org.apache.camel.processor.exceptionpolicy.ExceptionPolicyStrategy;
-import org.apache.camel.spi.ClassResolver;
-import org.apache.camel.spi.RouteContext;
 import org.apache.camel.support.ChildServiceSupport;
 
 /**
@@ -40,59 +33,25 @@ import org.apache.camel.support.ChildServiceSupport;
  */
 public abstract class ErrorHandlerSupport extends ChildServiceSupport implements ErrorHandler {
 
-    protected final Map<ExceptionPolicyKey, OnExceptionDefinition> exceptionPolicies = new LinkedHashMap<>();
+    protected final Map<ExceptionPolicyKey, ExceptionPolicy> exceptionPolicies = new LinkedHashMap<>();
     protected ExceptionPolicyStrategy exceptionPolicy = createDefaultExceptionPolicyStrategy();
 
-    public void addExceptionPolicy(RouteContext routeContext, OnExceptionDefinition exceptionType) {
-        if (routeContext != null) {
-            // add error handler as child service so they get lifecycle handled
-            Processor errorHandler = routeContext.getOnException(exceptionType.getId());
-            if (errorHandler != null) {
-                addChildService(errorHandler);
-            }
-
-            // load exception classes
-            List<Class<? extends Throwable>> list = null;
-            if (exceptionType.getExceptions() != null && !exceptionType.getExceptions().isEmpty()) {
-                list = createExceptionClasses(exceptionType, routeContext.getCamelContext().getClassResolver());
-                for (Class<? extends Throwable> clazz : list) {
-                    String routeId = null;
-                    // only get the route id, if the exception type is route scoped
-                    if (exceptionType.isRouteScoped()) {
-                        RouteDefinition route = ProcessorDefinitionHelper.getRoute(exceptionType);
-                        if (route != null) {
-                            routeId = route.getId();
-                        }
-                    }
-                    ExceptionPolicyKey key = new ExceptionPolicyKey(routeId, clazz, exceptionType.getOnWhen());
-                    exceptionPolicies.put(key, exceptionType);
-                }
-            }
-        }
+    public void addErrorHandler(Processor errorHandler) {
+        addChildService(errorHandler);
     }
 
-    protected List<Class<? extends Throwable>> createExceptionClasses(OnExceptionDefinition exceptionType, ClassResolver resolver) {
-        List<String> list = exceptionType.getExceptions();
-        List<Class<? extends Throwable>> answer = new ArrayList<>(list.size());
-        for (String name : list) {
-            try {
-                Class<? extends Throwable> type = resolver.resolveMandatoryClass(name, Throwable.class);
-                answer.add(type);
-            } catch (ClassNotFoundException e) {
-                throw RuntimeCamelException.wrapRuntimeCamelException(e);
-            }
-        }
-        return answer;
+    public void addExceptionPolicy(ExceptionPolicyKey key, ExceptionPolicy policy) {
+        exceptionPolicies.put(key, policy);
     }
 
     /**
-     * Attempts to find the best suited {@link OnExceptionDefinition} to be used for handling the given thrown exception.
+     * Attempts to find the best suited {@link ExceptionPolicy} 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 OnExceptionDefinition getExceptionPolicy(Exchange exchange, Throwable exception) {
+    protected ExceptionPolicy getExceptionPolicy(Exchange exchange, Throwable exception) {
         if (exceptionPolicy == null) {
             throw new IllegalStateException("The exception policy has not been set");
         }
@@ -101,7 +60,7 @@ public abstract class ErrorHandlerSupport extends ChildServiceSupport implements
     }
 
     /**
-     * Sets the strategy to use for resolving the {@link OnExceptionDefinition} to use
+     * Sets the strategy to use for resolving the {@link ExceptionPolicy} to use
      * for handling thrown exceptions.
      */
     public void setExceptionPolicy(ExceptionPolicyStrategy exceptionPolicy) {
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryErrorHandler.java b/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryErrorHandler.java
index 754c990..17d5423 100644
--- a/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryErrorHandler.java
+++ b/core/camel-core/src/main/java/org/apache/camel/processor/errorhandler/RedeliveryErrorHandler.java
@@ -36,8 +36,7 @@ import org.apache.camel.Navigate;
 import org.apache.camel.Predicate;
 import org.apache.camel.Processor;
 import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.model.OnExceptionDefinition;
-import org.apache.camel.reifier.ErrorHandlerReifier;
+import org.apache.camel.processor.exceptionpolicy.ExceptionPolicy;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
 import org.apache.camel.spi.CamelLogger;
 import org.apache.camel.spi.ExchangeFormatter;
@@ -664,13 +663,13 @@ public abstract class RedeliveryErrorHandler extends ErrorHandlerSupport impleme
             exchange.setProperty(Exchange.EXCEPTION_CAUGHT, e);
 
             // find the error handler to use (if any)
-            OnExceptionDefinition exceptionPolicy = getExceptionPolicy(exchange, e);
+            ExceptionPolicy exceptionPolicy = getExceptionPolicy(exchange, e);
             if (exceptionPolicy != null) {
-                currentRedeliveryPolicy = ErrorHandlerReifier.createRedeliveryPolicy(exceptionPolicy, exchange.getContext(), currentRedeliveryPolicy);
+                currentRedeliveryPolicy = exceptionPolicy.createRedeliveryPolicy(exchange.getContext(), currentRedeliveryPolicy);
                 handledPredicate = exceptionPolicy.getHandledPolicy();
                 continuedPredicate = exceptionPolicy.getContinuedPolicy();
                 retryWhilePredicate = exceptionPolicy.getRetryWhilePolicy();
-                useOriginalInMessage = exceptionPolicy.getUseOriginalMessagePolicy() != null && exceptionPolicy.getUseOriginalMessagePolicy();
+                useOriginalInMessage = exceptionPolicy.getUseOriginalInMessage();
 
                 // route specific failure handler?
                 Processor processor = null;
@@ -1245,25 +1244,8 @@ public abstract class RedeliveryErrorHandler extends ErrorHandlerSupport impleme
         // or on the exception policies
         if (!exceptionPolicies.isEmpty()) {
             // walk them to see if any of them have a maximum redeliveries > 0 or retry until set
-            for (OnExceptionDefinition def : exceptionPolicies.values()) {
-
-                String ref = def.getRedeliveryPolicyRef();
-                if (ref != null) {
-                    // lookup in registry if ref provided
-                    RedeliveryPolicy policy = CamelContextHelper.mandatoryLookup(camelContext, ref, RedeliveryPolicy.class);
-                    if (policy.getMaximumRedeliveries() != 0) {
-                        // must check for != 0 as (-1 means redeliver forever)
-                        return true;
-                    }
-                } else if (def.getRedeliveryPolicyType() != null) {
-                    Integer max = CamelContextHelper.parseInteger(camelContext, def.getRedeliveryPolicyType().getMaximumRedeliveries());
-                    if (max != null && max != 0) {
-                        // must check for != 0 as (-1 means redeliver forever)
-                        return true;
-                    }
-                }
-
-                if (def.getRetryWhilePolicy() != null || def.getRetryWhile() != null) {
+            for (ExceptionPolicy def : exceptionPolicies.values()) {
+                if (def.determineIfRedeliveryIsEnabled(camelContext)) {
                     return true;
                 }
             }
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java b/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
index 948d05a..3c5b660 100644
--- a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
+++ b/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
@@ -23,15 +23,12 @@ import java.util.Set;
 import java.util.TreeMap;
 
 import org.apache.camel.Exchange;
-import org.apache.camel.model.OnExceptionDefinition;
-import org.apache.camel.model.ProcessorDefinitionHelper;
-import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * The default strategy used in Camel to resolve the {@link org.apache.camel.model.OnExceptionDefinition} that should
+ * The default strategy used in Camel to resolve the {@link ExceptionPolicy} that should
  * handle the thrown exception.
  * <p/>
  * <b>Selection strategy:</b>
@@ -41,7 +38,7 @@ import org.slf4j.LoggerFactory;
  * by is selected first, ending with the thrown exception itself. The method {@link #createExceptionIterator(Throwable)}
  * provides the Iterator used for the walking.</li>
  * <li>The exception type must be configured with an Exception that is an instance of the thrown exception, this
- * is tested using the {@link #filter(org.apache.camel.model.OnExceptionDefinition, Class, Throwable)} method.
+ * is tested using the {@link #filter(ExceptionPolicy, Class, Throwable)} method.
  * By default the filter uses <tt>instanceof</tt> test.</li>
  * <li>If the exception type has <b>exactly</b> the thrown exception then its selected as its an exact match</li>
  * <li>Otherwise the type that has an exception that is the closest super of the thrown exception is selected
@@ -49,8 +46,8 @@ import org.slf4j.LoggerFactory;
  * </ul>
  * <p/>
  * <b>Fine grained matching:</b>
- * <br/> If the {@link OnExceptionDefinition} has a when defined with an expression the type is also matches against
- * the current exchange using the {@link #matchesWhen(org.apache.camel.model.OnExceptionDefinition, org.apache.camel.Exchange)}
+ * <br/> If the {@link ExceptionPolicy} has a when defined with an expression the type is also matches against
+ * the current exchange using the {@link #matchesWhen(ExceptionPolicy, org.apache.camel.Exchange)}
  * method. This can be used to for more fine grained matching, so you can e.g. define multiple sets of
  * exception types with the same exception class(es) but have a predicate attached to select which to select at runtime.
  */
@@ -58,12 +55,12 @@ public class DefaultExceptionPolicyStrategy implements ExceptionPolicyStrategy {
 
     private static final Logger LOG = LoggerFactory.getLogger(DefaultExceptionPolicyStrategy.class);
 
-    public OnExceptionDefinition getExceptionPolicy(Map<ExceptionPolicyKey, OnExceptionDefinition> exceptionPolicies,
-                                                    Exchange exchange, Throwable exception) {
+    public ExceptionPolicy getExceptionPolicy(Map<ExceptionPolicyKey, ExceptionPolicy> exceptionPolicies,
+                                              Exchange exchange, Throwable exception) {
 
-        Map<Integer, OnExceptionDefinition> candidates = new TreeMap<>();
-        Map<ExceptionPolicyKey, OnExceptionDefinition> routeScoped = new LinkedHashMap<>();
-        Map<ExceptionPolicyKey, OnExceptionDefinition> contextScoped = new LinkedHashMap<>();
+        Map<Integer, ExceptionPolicy> candidates = new TreeMap<>();
+        Map<ExceptionPolicyKey, ExceptionPolicy> routeScoped = new LinkedHashMap<>();
+        Map<ExceptionPolicyKey, ExceptionPolicy> contextScoped = new LinkedHashMap<>();
 
         // split policies into route and context scoped
         initRouteAndContextScopedExceptionPolicies(exceptionPolicies, routeScoped, contextScoped);
@@ -96,13 +93,13 @@ public class DefaultExceptionPolicyStrategy implements ExceptionPolicyStrategy {
         }
     }
 
-    private void initRouteAndContextScopedExceptionPolicies(Map<ExceptionPolicyKey, OnExceptionDefinition> exceptionPolicies,
-                                                            Map<ExceptionPolicyKey, OnExceptionDefinition> routeScoped,
-                                                            Map<ExceptionPolicyKey, OnExceptionDefinition> contextScoped) {
+    private void initRouteAndContextScopedExceptionPolicies(Map<ExceptionPolicyKey, ExceptionPolicy> exceptionPolicies,
+                                                            Map<ExceptionPolicyKey, ExceptionPolicy> routeScoped,
+                                                            Map<ExceptionPolicyKey, ExceptionPolicy> contextScoped) {
 
         // loop through all the entries and split into route and context scoped
-        Set<Map.Entry<ExceptionPolicyKey, OnExceptionDefinition>> entries = exceptionPolicies.entrySet();
-        for (Map.Entry<ExceptionPolicyKey, OnExceptionDefinition> entry : entries) {
+        Set<Map.Entry<ExceptionPolicyKey, ExceptionPolicy>> entries = exceptionPolicies.entrySet();
+        for (Map.Entry<ExceptionPolicyKey, ExceptionPolicy> entry : entries) {
             if (entry.getKey().getRouteId() != null) {
                 routeScoped.put(entry.getKey(), entry.getValue());
             } else {
@@ -112,9 +109,9 @@ public class DefaultExceptionPolicyStrategy implements ExceptionPolicyStrategy {
     }
 
 
-    private boolean findMatchedExceptionPolicy(Map<ExceptionPolicyKey, OnExceptionDefinition> exceptionPolicies,
+    private boolean findMatchedExceptionPolicy(Map<ExceptionPolicyKey, ExceptionPolicy> exceptionPolicies,
                                                Exchange exchange, Throwable exception,
-                                               Map<Integer, OnExceptionDefinition> candidates) {
+                                               Map<Integer, ExceptionPolicy> candidates) {
         if (LOG.isTraceEnabled()) {
             LOG.trace("Finding best suited exception policy for thrown exception {}", exception.getClass().getName());
         }
@@ -122,21 +119,21 @@ public class DefaultExceptionPolicyStrategy implements ExceptionPolicyStrategy {
         // 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 to return
-        OnExceptionDefinition candidate = null;
+        ExceptionPolicy 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<ExceptionPolicyKey, OnExceptionDefinition>> entries = exceptionPolicies.entrySet();
-        for (Map.Entry<ExceptionPolicyKey, OnExceptionDefinition> entry : entries) {
+        Set<Map.Entry<ExceptionPolicyKey, ExceptionPolicy>> entries = exceptionPolicies.entrySet();
+        for (Map.Entry<ExceptionPolicyKey, ExceptionPolicy> entry : entries) {
             Class<?> clazz = entry.getKey().getExceptionClass();
-            OnExceptionDefinition type = entry.getValue();
+            ExceptionPolicy type = entry.getValue();
 
-            // if OnException is route scoped then the current route (Exchange) must match
-            // so we will not pick an OnException from another route
+            // if ExceptionPolicy is route scoped then the current route (Exchange) must match
+            // so we will not pick an ExceptionPolicy from another route
             if (exchange != null && exchange.getUnitOfWork() != null && type.isRouteScoped()) {
                 String route = exchange.getUnitOfWork().getRouteContext() != null ? exchange.getUnitOfWork().getRouteContext().getRouteId() : null;
-                String typeRoute = ProcessorDefinitionHelper.getRouteId(type);
+                String typeRoute = type.getRouteId();
                 if (route != null && typeRoute != null && !route.equals(typeRoute)) {
                     if (LOG.isTraceEnabled()) {
                         LOG.trace("The type is scoped for route: {} however Exchange is at route: {}", typeRoute, route);
@@ -203,7 +200,7 @@ public class DefaultExceptionPolicyStrategy implements ExceptionPolicyStrategy {
      * @param exception      the thrown exception
      * @return <tt>true</tt> if the to current exception class is a candidate, <tt>false</tt> to skip it.
      */
-    protected boolean filter(OnExceptionDefinition type, Class<?> exceptionClass, Throwable exception) {
+    protected boolean filter(ExceptionPolicy type, Class<?> exceptionClass, Throwable exception) {
         // must be instance of check to ensure that the exceptionClass is one type of the thrown exception
         return exceptionClass.isInstance(exception);
     }
@@ -221,17 +218,17 @@ public class DefaultExceptionPolicyStrategy implements ExceptionPolicyStrategy {
      * @param exchange the current {@link Exchange}
      * @return <tt>true</tt> if matched, <tt>false</tt> otherwise.
      */
-    protected boolean matchesWhen(OnExceptionDefinition definition, Exchange exchange) {
-        if (definition.getOnWhen() == null || definition.getOnWhen().getExpression() == null) {
+    protected boolean matchesWhen(ExceptionPolicy definition, Exchange exchange) {
+        if (definition.getOnWhen() == null || definition.getOnWhen() == null) {
             // if no predicate then it's always a match
             return true;
         }
-        return definition.getOnWhen().getExpression().matches(exchange);
+        return definition.getOnWhen().matches(exchange);
     }
 
     /**
      * Strategy method creating the iterator to walk the exception in the order Camel should use
-     * for find the {@link OnExceptionDefinition} should be used.
+     * for find the {@link ExceptionPolicy} should be used.
      * <p/>
      * The default iterator will walk from the bottom upwards
      * (the last caused by going upwards to the exception)
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicy.java b/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicy.java
new file mode 100644
index 0000000..cb0cecd
--- /dev/null
+++ b/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicy.java
@@ -0,0 +1,85 @@
+package org.apache.camel.processor.exceptionpolicy;
+
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Predicate;
+import org.apache.camel.Processor;
+import org.apache.camel.model.OnExceptionDefinition;
+import org.apache.camel.model.ProcessorDefinitionHelper;
+import org.apache.camel.model.RedeliveryPolicyDefinition;
+import org.apache.camel.processor.errorhandler.RedeliveryPolicy;
+import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
+
+public class ExceptionPolicy {
+
+    private final OnExceptionDefinition def;
+
+    public ExceptionPolicy(OnExceptionDefinition def) {
+        this.def = def;
+    }
+
+    public String getId() {
+        return def.getId();
+    }
+
+    public String getRouteId() {
+        return ProcessorDefinitionHelper.getRouteId(def);
+    }
+
+    public boolean isRouteScoped() {
+        return def.getRouteScoped() != null && def.getRouteScoped();
+    }
+
+    public Predicate getOnWhen() {
+        return def.getOnWhen() != null ? def.getOnWhen().getExpression() : null;
+    }
+
+    public String getRedeliveryPolicyRef() {
+        return def.getRedeliveryPolicyRef();
+    }
+
+    public boolean hasOutputs() {
+        return def.getOutputs() != null && !def.getOutputs().isEmpty();
+    }
+
+    public RedeliveryPolicyDefinition getRedeliveryPolicyType() {
+        return def.getRedeliveryPolicyType();
+    }
+
+    public Predicate getHandledPolicy() {
+        return def.getHandledPolicy();
+    }
+
+    public Predicate getContinuedPolicy() {
+        return def.getContinuedPolicy();
+    }
+
+    public Predicate getRetryWhilePolicy() {
+        return def.getRetryWhilePolicy();
+    }
+
+    public boolean getUseOriginalInMessage() {
+        return def.getUseOriginalMessagePolicy() != null && def.getUseOriginalMessagePolicy();
+    }
+
+    public Processor getOnRedelivery() {
+        return def.getOnRedelivery();
+    }
+
+    public Processor getOnExceptionOccurred() {
+        return def.getOnExceptionOccurred();
+    }
+
+    public List<String> getExceptions() {
+        return def.getExceptions();
+    }
+
+    public boolean determineIfRedeliveryIsEnabled(CamelContext context) throws Exception {
+        return ErrorHandlerReifier.determineIfRedeliveryIsEnabled(this, context);
+    }
+
+    public RedeliveryPolicy createRedeliveryPolicy(CamelContext context, RedeliveryPolicy parent) {
+        return ErrorHandlerReifier.createRedeliveryPolicy(this, context, parent);
+    }
+}
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyKey.java b/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyKey.java
index f564cbe..8efdf59 100644
--- a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyKey.java
+++ b/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyKey.java
@@ -16,7 +16,7 @@
  */
 package org.apache.camel.processor.exceptionpolicy;
 
-import org.apache.camel.model.WhenDefinition;
+import org.apache.camel.Predicate;
 
 /**
  * Exception policy key is a compound key for storing:
@@ -28,7 +28,7 @@ public final class ExceptionPolicyKey {
 
     private final String routeId;
     private final Class<? extends Throwable> exceptionClass;
-    private final WhenDefinition when;
+    private final Predicate when;
 
     /**
      * Key for exception clause
@@ -37,7 +37,7 @@ public final class ExceptionPolicyKey {
      * @param exceptionClass   the exception class
      * @param when             optional predicate when the exception clause should trigger
      */
-    public ExceptionPolicyKey(String routeId, Class<? extends Throwable> exceptionClass, WhenDefinition when) {
+    public ExceptionPolicyKey(String routeId, Class<? extends Throwable> exceptionClass, Predicate when) {
         this.routeId = routeId;
         this.exceptionClass = exceptionClass;
         this.when = when;
@@ -47,7 +47,7 @@ public final class ExceptionPolicyKey {
         return exceptionClass;
     }
 
-    public WhenDefinition getWhen() {
+    public Predicate getWhen() {
         return when;
     }
 
diff --git a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java b/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java
index b192e71..482085a 100644
--- a/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java
+++ b/core/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ExceptionPolicyStrategy.java
@@ -19,10 +19,9 @@ package org.apache.camel.processor.exceptionpolicy;
 import java.util.Map;
 
 import org.apache.camel.Exchange;
-import org.apache.camel.model.OnExceptionDefinition;
 
 /**
- * A strategy to determine which {@link org.apache.camel.model.OnExceptionDefinition} should handle the thrown
+ * A strategy to determine which {@link ExceptionPolicy} should handle the thrown
  * exception.
  *
  * @see org.apache.camel.processor.exceptionpolicy.DefaultExceptionPolicyStrategy DefaultExceptionPolicy
@@ -30,14 +29,14 @@ import org.apache.camel.model.OnExceptionDefinition;
 public interface ExceptionPolicyStrategy {
 
     /**
-     * Resolves the {@link org.apache.camel.model.OnExceptionDefinition} that should handle the thrown exception.
+     * Resolves the {@link ExceptionPolicy} that should handle the thrown exception.
      *
      * @param exceptionPolicies 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.
      */
-    OnExceptionDefinition getExceptionPolicy(Map<ExceptionPolicyKey, OnExceptionDefinition> exceptionPolicies,
-                                             Exchange exchange, Throwable exception);
+    ExceptionPolicy getExceptionPolicy(Map<ExceptionPolicyKey, ExceptionPolicy> exceptionPolicies,
+                                       Exchange exchange, Throwable exception);
 
 }
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java
index 04eee55..f030abd 100644
--- a/core/camel-core/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/DynamicRouterReifier.java
@@ -24,6 +24,7 @@ import org.apache.camel.model.DynamicRouterDefinition;
 import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.processor.DynamicRouter;
+import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
 import org.apache.camel.spi.RouteContext;
 
 class DynamicRouterReifier extends ExpressionReifier<DynamicRouterDefinition<?>> {
@@ -49,7 +50,7 @@ class DynamicRouterReifier extends ExpressionReifier<DynamicRouterDefinition<?>>
         ErrorHandlerFactory builder = routeContext.getErrorHandlerFactory();
         // create error handler (create error handler directly to keep it light weight,
         // instead of using ProcessorDefinition.wrapInErrorHandler)
-        AsyncProcessor errorHandler = (AsyncProcessor) builder.createErrorHandler(routeContext, dynamicRouter.newRoutingSlipProcessorForErrorHandler());
+        AsyncProcessor errorHandler = (AsyncProcessor) ErrorHandlerReifier.reifier(builder).createErrorHandler(routeContext, dynamicRouter.newRoutingSlipProcessorForErrorHandler());
         dynamicRouter.setErrorHandler(errorHandler);
 
         return dynamicRouter;
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/OnExceptionReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/OnExceptionReifier.java
index 98d19f8..82e5ec7 100644
--- a/core/camel-core/src/main/java/org/apache/camel/reifier/OnExceptionReifier.java
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/OnExceptionReifier.java
@@ -26,6 +26,7 @@ import org.apache.camel.model.OnExceptionDefinition;
 import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.processor.CatchProcessor;
 import org.apache.camel.processor.FatalFallbackErrorHandler;
+import org.apache.camel.processor.exceptionpolicy.ExceptionPolicy;
 import org.apache.camel.spi.ClassResolver;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.support.CamelContextHelper;
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/ProcessorReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
index e42afe1..f689433 100644
--- a/core/camel-core/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
@@ -103,6 +103,7 @@ import org.apache.camel.processor.InterceptEndpointProcessor;
 import org.apache.camel.processor.Pipeline;
 import org.apache.camel.processor.channel.DefaultChannel;
 import org.apache.camel.processor.interceptor.HandleFault;
+import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
 import org.apache.camel.spi.IdAware;
 import org.apache.camel.spi.InterceptStrategy;
 import org.apache.camel.spi.LifecycleStrategy;
@@ -367,7 +368,7 @@ public abstract class ProcessorReifier<T extends ProcessorDefinition<?>> {
     protected Processor wrapInErrorHandler(RouteContext routeContext, Processor output) throws Exception {
         ErrorHandlerFactory builder = routeContext.getErrorHandlerFactory();
         // create error handler
-        Processor errorHandler = builder.createErrorHandler(routeContext, output);
+        Processor errorHandler = ErrorHandlerReifier.reifier(builder).createErrorHandler(routeContext, output);
 
         // invoke lifecycles so we can manage this error handler builder
         for (LifecycleStrategy strategy : routeContext.getCamelContext().getLifecycleStrategies()) {
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/RoutingSlipReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/RoutingSlipReifier.java
index 68089e0..bb3a706 100644
--- a/core/camel-core/src/main/java/org/apache/camel/reifier/RoutingSlipReifier.java
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/RoutingSlipReifier.java
@@ -25,6 +25,7 @@ import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RoutingSlipDefinition;
 
 import org.apache.camel.processor.RoutingSlip;
+import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier;
 import org.apache.camel.spi.RouteContext;
 
 import static org.apache.camel.model.RoutingSlipDefinition.DEFAULT_DELIMITER;
@@ -52,7 +53,7 @@ class RoutingSlipReifier extends ExpressionReifier<RoutingSlipDefinition<?>> {
         ErrorHandlerFactory builder = routeContext.getErrorHandlerFactory();
         // create error handler (create error handler directly to keep it light weight,
         // instead of using ProcessorDefinition.wrapInErrorHandler)
-        AsyncProcessor errorHandler = (AsyncProcessor) builder.createErrorHandler(routeContext, routingSlip.newRoutingSlipProcessorForErrorHandler());
+        AsyncProcessor errorHandler = (AsyncProcessor) ErrorHandlerReifier.reifier(builder).createErrorHandler(routeContext, routingSlip.newRoutingSlipProcessorForErrorHandler());
         routingSlip.setErrorHandler(errorHandler);
 
         return routingSlip;
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/DeadLetterChannelReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/DeadLetterChannelReifier.java
new file mode 100644
index 0000000..af841d0
--- /dev/null
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/DeadLetterChannelReifier.java
@@ -0,0 +1,48 @@
+package org.apache.camel.reifier.errorhandler;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.ErrorHandlerFactory;
+import org.apache.camel.NoSuchEndpointException;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.DeadLetterChannelBuilder;
+import org.apache.camel.processor.errorhandler.DeadLetterChannel;
+import org.apache.camel.spi.RouteContext;
+import org.apache.camel.util.StringHelper;
+
+public class DeadLetterChannelReifier extends DefaultErrorHandlerReifier<DeadLetterChannelBuilder> {
+
+    public DeadLetterChannelReifier(ErrorHandlerFactory definition) {
+        super((DeadLetterChannelBuilder) definition);
+    }
+
+    public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception {
+        validateDeadLetterUri(routeContext);
+
+        DeadLetterChannel answer = new DeadLetterChannel(routeContext.getCamelContext(), processor,
+                definition.getLogger(), definition.getOnRedelivery(),
+                definition.getRedeliveryPolicy(), definition.getExceptionPolicyStrategy(),
+                definition.getFailureProcessor(), definition.getDeadLetterUri(),
+                definition.isDeadLetterHandleNewException(), definition.isUseOriginalMessage(),
+                definition.getRetryWhilePolicy(routeContext.getCamelContext()),
+                getExecutorService(routeContext.getCamelContext()),
+                definition.getOnPrepareFailure(), definition.getOnExceptionOccurred());
+        // configure error handler before we can use it
+        configure(routeContext, answer);
+        return answer;
+    }
+
+    protected void validateDeadLetterUri(RouteContext routeContext) {
+        Endpoint deadLetter = definition.getDeadLetter();
+        String deadLetterUri = definition.getDeadLetterUri();
+        if (deadLetter == null) {
+            StringHelper.notEmpty(deadLetterUri, "deadLetterUri", this);
+            deadLetter = routeContext.getCamelContext().getEndpoint(deadLetterUri);
+            if (deadLetter == null) {
+                throw new NoSuchEndpointException(deadLetterUri);
+            }
+            // TODO: ErrorHandler: no modification to the model should be done
+            definition.setDeadLetter(deadLetter);
+        }
+    }
+
+}
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/DefaultErrorHandlerReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/DefaultErrorHandlerReifier.java
new file mode 100644
index 0000000..a262509a
--- /dev/null
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/DefaultErrorHandlerReifier.java
@@ -0,0 +1,69 @@
+package org.apache.camel.reifier.errorhandler;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.ErrorHandlerFactory;
+import org.apache.camel.NoSuchEndpointException;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.DeadLetterChannelBuilder;
+import org.apache.camel.builder.DefaultErrorHandlerBuilder;
+import org.apache.camel.processor.errorhandler.DeadLetterChannel;
+import org.apache.camel.processor.errorhandler.DefaultErrorHandler;
+import org.apache.camel.spi.ExecutorServiceManager;
+import org.apache.camel.spi.RouteContext;
+import org.apache.camel.spi.ThreadPoolProfile;
+import org.apache.camel.util.StringHelper;
+
+public class DefaultErrorHandlerReifier<T extends DefaultErrorHandlerBuilder> extends ErrorHandlerReifier<T> {
+
+    public DefaultErrorHandlerReifier(ErrorHandlerFactory definition) {
+        super((T) definition);
+    }
+
+    public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception {
+        DefaultErrorHandler answer = new DefaultErrorHandler(
+                routeContext.getCamelContext(),
+                processor,
+                definition.getLogger(),
+                definition.getOnRedelivery(),
+                definition.getRedeliveryPolicy(),
+                definition.getExceptionPolicyStrategy(),
+                definition.getRetryWhilePolicy(routeContext.getCamelContext()),
+                getExecutorService(routeContext.getCamelContext()),
+                definition.getOnPrepareFailure(),
+                definition.getOnExceptionOccurred());
+        // configure error handler before we can use it
+        configure(routeContext, answer);
+        return answer;
+    }
+
+    protected synchronized ScheduledExecutorService getExecutorService(CamelContext camelContext) {
+        ScheduledExecutorService executorService = definition.getExecutorService();
+        String executorServiceRef = definition.getExecutorServiceRef();
+        if (executorService == null || executorService.isShutdown()) {
+            // camel context will shutdown the executor when it shutdown so no need to shut it down when stopping
+            if (executorServiceRef != null) {
+                executorService = camelContext.getRegistry().lookupByNameAndType(executorServiceRef, ScheduledExecutorService.class);
+                if (executorService == null) {
+                    ExecutorServiceManager manager = camelContext.getExecutorServiceManager();
+                    ThreadPoolProfile profile = manager.getThreadPoolProfile(executorServiceRef);
+                    executorService = manager.newScheduledThreadPool(this, executorServiceRef, profile);
+                }
+                if (executorService == null) {
+                    throw new IllegalArgumentException("ExecutorServiceRef " + executorServiceRef + " not found in registry.");
+                }
+            } else {
+                // no explicit configured thread pool, so leave it up to the error handler to decide if it need
+                // a default thread pool from CamelContext#getErrorHandlerExecutorService
+                executorService = null;
+            }
+            // TODO: ErrorHandler: no modification to the model should be done
+            definition.setExecutorService(executorService);
+        }
+        return executorService;
+    }
+
+}
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerRefReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerRefReifier.java
new file mode 100644
index 0000000..f35173f
--- /dev/null
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerRefReifier.java
@@ -0,0 +1,19 @@
+package org.apache.camel.reifier.errorhandler;
+
+import org.apache.camel.ErrorHandlerFactory;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.ErrorHandlerBuilderRef;
+import org.apache.camel.spi.RouteContext;
+
+public class ErrorHandlerRefReifier extends ErrorHandlerReifier<ErrorHandlerBuilderRef> {
+
+    public ErrorHandlerRefReifier(ErrorHandlerFactory definition) {
+        super((ErrorHandlerBuilderRef) definition);
+    }
+
+    @Override
+    public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception {
+        return definition.createErrorHandler(routeContext, processor);
+    }
+
+}
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/ErrorHandlerReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java
similarity index 59%
rename from core/camel-core/src/main/java/org/apache/camel/reifier/ErrorHandlerReifier.java
rename to core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java
index 57eb65b..c0b90c4 100644
--- a/core/camel-core/src/main/java/org/apache/camel/reifier/ErrorHandlerReifier.java
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/ErrorHandlerReifier.java
@@ -14,21 +14,103 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.reifier;
+package org.apache.camel.reifier.errorhandler;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.function.Function;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.ErrorHandlerFactory;
+import org.apache.camel.Processor;
 import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.builder.DeadLetterChannelBuilder;
+import org.apache.camel.builder.DefaultErrorHandlerBuilder;
+import org.apache.camel.builder.ErrorHandlerBuilderRef;
+import org.apache.camel.builder.ErrorHandlerBuilderSupport;
+import org.apache.camel.builder.NoErrorHandlerBuilder;
 import org.apache.camel.model.OnExceptionDefinition;
 import org.apache.camel.model.RedeliveryPolicyDefinition;
+import org.apache.camel.processor.ErrorHandler;
+import org.apache.camel.processor.errorhandler.ErrorHandlerSupport;
+import org.apache.camel.processor.errorhandler.RedeliveryErrorHandler;
 import org.apache.camel.processor.errorhandler.RedeliveryPolicy;
+import org.apache.camel.processor.exceptionpolicy.ExceptionPolicy;
+import org.apache.camel.spi.RouteContext;
 import org.apache.camel.support.CamelContextHelper;
 
-public final class ErrorHandlerReifier {
-    
+public abstract class ErrorHandlerReifier<T extends ErrorHandlerBuilderSupport> {
+
+    private static final Map<Class<?>, Function<ErrorHandlerFactory, ErrorHandlerReifier<? extends ErrorHandlerFactory>>> ERROR_HANDLERS;
+    static {
+        Map<Class<?>, Function<ErrorHandlerFactory, ErrorHandlerReifier<? extends ErrorHandlerFactory>>> map = new HashMap<>();
+        map.put(DeadLetterChannelBuilder.class, DeadLetterChannelReifier::new);
+        map.put(DefaultErrorHandlerBuilder.class, DefaultErrorHandlerReifier::new);
+        map.put(ErrorHandlerBuilderRef.class, ErrorHandlerRefReifier::new);
+        map.put(NoErrorHandlerBuilder.class, NoErrorHandlerReifier::new);
+        ERROR_HANDLERS = map;
+    }
+
+    public static void registerReifier(Class<?> errorHandlerClass, Function<ErrorHandlerFactory, ErrorHandlerReifier<? extends ErrorHandlerFactory>> creator) {
+        ERROR_HANDLERS.put(errorHandlerClass, creator);
+    }
+
+    protected T definition;
+
     /**
      * Utility classes should not have a public constructor.
      */
-    private ErrorHandlerReifier() {
+    ErrorHandlerReifier(T definition) {
+        this.definition = definition;
+    }
+
+    public static ErrorHandlerReifier<? extends ErrorHandlerFactory> reifier(ErrorHandlerFactory definition) {
+        Function<ErrorHandlerFactory, ErrorHandlerReifier<? extends ErrorHandlerFactory>> reifier = ERROR_HANDLERS.get(definition.getClass());
+        if (reifier != null) {
+            return reifier.apply(definition);
+        } else if (definition instanceof ErrorHandlerBuilderSupport) {
+            return new ErrorHandlerReifier<ErrorHandlerBuilderSupport>((ErrorHandlerBuilderSupport) definition) {
+                @Override
+                public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception {
+                    return definition.createErrorHandler(routeContext, processor);
+                }
+            };
+        } else {
+            throw new IllegalStateException("Unsupported definition: " + definition);
+        }
+    }
+
+    /**
+     * Creates the error handler
+     *
+     * @param routeContext the route context
+     * @param processor the outer processor
+     * @return the error handler
+     * @throws Exception is thrown if the error handler could not be created
+     */
+    public abstract Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception;
+
+    public void configure(RouteContext routeContext, ErrorHandler handler) {
+        if (handler instanceof ErrorHandlerSupport) {
+            ErrorHandlerSupport handlerSupport = (ErrorHandlerSupport) handler;
+
+            List<OnExceptionDefinition> list = definition.getOnExceptions().get(routeContext);
+            if (list != null) {
+                for (OnExceptionDefinition exception : list) {
+                    ErrorHandlerBuilderSupport.addExceptionPolicy(handlerSupport, routeContext, exception);
+                }
+            }
+        }
+        if (handler instanceof RedeliveryErrorHandler) {
+            boolean original = ((RedeliveryErrorHandler) handler).isUseOriginalMessagePolicy();
+            if (original) {
+                // ensure allow original is turned on
+                routeContext.setAllowUseOriginalMessage(true);
+            }
+        }
     }
 
     public static RedeliveryPolicy createRedeliveryPolicy(RedeliveryPolicyDefinition definition, CamelContext context, RedeliveryPolicy parentPolicy) {
@@ -133,12 +215,12 @@ public final class ErrorHandlerReifier {
      * @return a newly created redelivery policy, or return the original policy if no customization is required
      *         for this exception handler.
      */
-    public static RedeliveryPolicy createRedeliveryPolicy(OnExceptionDefinition definition, CamelContext context, RedeliveryPolicy parentPolicy) {
+    public static RedeliveryPolicy createRedeliveryPolicy(ExceptionPolicy definition, CamelContext context, RedeliveryPolicy parentPolicy) {
         if (definition.getRedeliveryPolicyRef() != null) {
             return CamelContextHelper.mandatoryLookup(context, definition.getRedeliveryPolicyRef(), RedeliveryPolicy.class);
         } else if (definition.getRedeliveryPolicyType() != null) {
             return createRedeliveryPolicy(definition.getRedeliveryPolicyType(), context, parentPolicy);
-        } else if (!definition.getOutputs().isEmpty() && parentPolicy.getMaximumRedeliveries() != 0) {
+        } else if (definition.hasOutputs() && parentPolicy.getMaximumRedeliveries() != 0) {
             // if we have outputs, then do not inherit parent maximumRedeliveries
             // as you would have to explicit configure maximumRedeliveries on this onException to use it
             // this is the behavior Camel has always had
@@ -149,4 +231,28 @@ public final class ErrorHandlerReifier {
             return parentPolicy;
         }
     }
+
+    public static boolean determineIfRedeliveryIsEnabled(ExceptionPolicy def, CamelContext camelContext) throws Exception {
+        String ref = def.getRedeliveryPolicyRef();
+        if (ref != null) {
+            // lookup in registry if ref provided
+            RedeliveryPolicy policy = CamelContextHelper.mandatoryLookup(camelContext, ref, RedeliveryPolicy.class);
+            if (policy.getMaximumRedeliveries() != 0) {
+                // must check for != 0 as (-1 means redeliver forever)
+                return true;
+            }
+        } else if (def.getRedeliveryPolicyType() != null) {
+            Integer max = CamelContextHelper.parseInteger(camelContext, def.getRedeliveryPolicyType().getMaximumRedeliveries());
+            if (max != null && max != 0) {
+                // must check for != 0 as (-1 means redeliver forever)
+                return true;
+            }
+        }
+
+        if (def.getRetryWhilePolicy() != null) {
+            return true;
+        }
+
+        return false;
+    }
 }
diff --git a/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/NoErrorHandlerReifier.java b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/NoErrorHandlerReifier.java
new file mode 100644
index 0000000..89dde35
--- /dev/null
+++ b/core/camel-core/src/main/java/org/apache/camel/reifier/errorhandler/NoErrorHandlerReifier.java
@@ -0,0 +1,41 @@
+package org.apache.camel.reifier.errorhandler;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.ErrorHandlerFactory;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.NoErrorHandlerBuilder;
+import org.apache.camel.spi.RouteContext;
+import org.apache.camel.support.processor.DelegateAsyncProcessor;
+
+public class NoErrorHandlerReifier extends ErrorHandlerReifier<NoErrorHandlerBuilder> {
+
+    public NoErrorHandlerReifier(ErrorHandlerFactory definition) {
+        super((NoErrorHandlerBuilder) definition);
+    }
+
+    @Override
+    public Processor createErrorHandler(RouteContext routeContext, Processor processor) throws Exception {
+        return new DelegateAsyncProcessor(processor) {
+            @Override
+            public boolean process(final Exchange exchange, final AsyncCallback callback) {
+                return super.process(exchange, new AsyncCallback() {
+                    @Override
+                    public void done(boolean doneSync) {
+                        exchange.removeProperty(Exchange.REDELIVERY_EXHAUSTED);
+                        callback.done(doneSync);
+                    }
+                });
+            }
+
+            @Override
+            public String toString() {
+                if (processor == null) {
+                    // if no output then dont do any description
+                    return "";
+                }
+                return "NoErrorHandler[" + processor + "]";
+            }
+        };
+    }
+}
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorEndpointClearCachedSchemaTest.java b/core/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorEndpointClearCachedSchemaTest.java
index 0566c3a..1a2b006 100644
--- a/core/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorEndpointClearCachedSchemaTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/component/validator/ValidatorEndpointClearCachedSchemaTest.java
@@ -30,6 +30,7 @@ import org.apache.camel.Exchange;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.support.CamelContextHelper;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -142,6 +143,10 @@ public class ValidatorEndpointClearCachedSchemaTest extends ContextTestSupport {
     }
 
     private void clearCachedSchema() throws Exception {
+        CamelContext context = this.context;
+        if (context == null) {
+            return;
+        }
         Collection<Endpoint> endpoints = context.getEndpoints();
         for (Endpoint endpoint : endpoints) {
             LOG.info("Endpoint URI: " + endpoint.getEndpointUri());
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupportTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupportTest.java
index 801ebd0..833e71b 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupportTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/errorhandler/ErrorHandlerSupportTest.java
@@ -22,6 +22,7 @@ import java.util.List;
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
+import org.apache.camel.builder.ErrorHandlerBuilderSupport;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.model.OnExceptionDefinition;
 import org.junit.Test;
@@ -35,7 +36,7 @@ public class ErrorHandlerSupportTest extends ContextTestSupport {
         exceptions.add(ParentException.class);
 
         ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
-        support.addExceptionPolicy(context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(exceptions));
+        ErrorHandlerBuilderSupport.addExceptionPolicy(support, context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(exceptions));
 
         assertEquals(ChildException.class.getName(), getExceptionPolicyFor(support, new ChildException(), 0));
         assertEquals(ParentException.class.getName(), getExceptionPolicyFor(support, new ParentException(), 1));
@@ -48,7 +49,7 @@ public class ErrorHandlerSupportTest extends ContextTestSupport {
         exceptions.add(ChildException.class);
 
         ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
-        support.addExceptionPolicy(context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(exceptions));
+        ErrorHandlerBuilderSupport.addExceptionPolicy(support, context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(exceptions));
 
         assertEquals(ChildException.class.getName(), getExceptionPolicyFor(support, new ChildException(), 1));
         assertEquals(ParentException.class.getName(), getExceptionPolicyFor(support, new ParentException(), 0));
@@ -57,8 +58,8 @@ public class ErrorHandlerSupportTest extends ContextTestSupport {
     @Test
     public void testTwoPolicyChildFirst() {
         ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
-        support.addExceptionPolicy(context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(ChildException.class));
-        support.addExceptionPolicy(context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(ParentException.class));
+        ErrorHandlerBuilderSupport.addExceptionPolicy(support, context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(ChildException.class));
+        ErrorHandlerBuilderSupport.addExceptionPolicy(support, context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(ParentException.class));
 
         assertEquals(ChildException.class.getName(), getExceptionPolicyFor(support, new ChildException(), 0));
         assertEquals(ParentException.class.getName(), getExceptionPolicyFor(support, new ParentException(), 0));
@@ -67,8 +68,8 @@ public class ErrorHandlerSupportTest extends ContextTestSupport {
     @Test
     public void testTwoPolicyChildLast() {
         ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
-        support.addExceptionPolicy(context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(ParentException.class));
-        support.addExceptionPolicy(context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(ChildException.class));
+        ErrorHandlerBuilderSupport.addExceptionPolicy(support, context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(ParentException.class));
+        ErrorHandlerBuilderSupport.addExceptionPolicy(support, context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(ChildException.class));
 
         assertEquals(ChildException.class.getName(), getExceptionPolicyFor(support, new ChildException(), 0));
         assertEquals(ParentException.class.getName(), getExceptionPolicyFor(support, new ParentException(), 0));
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
index 4c36a10..f6cb8b8 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
@@ -25,7 +25,6 @@ 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.OnExceptionDefinition;
 import org.junit.Test;
 
 /**
@@ -43,7 +42,7 @@ public class CustomExceptionPolicyStrategyTest extends ContextTestSupport {
     // START SNIPPET e2
     public static class MyPolicy implements ExceptionPolicyStrategy {
 
-        public OnExceptionDefinition getExceptionPolicy(Map<ExceptionPolicyKey, OnExceptionDefinition> exceptionPolicices,
+        public ExceptionPolicy getExceptionPolicy(Map<ExceptionPolicyKey, ExceptionPolicy> exceptionPolicices,
                                                 Exchange exchange,
                                                 Throwable exception) {
             // This is just an example that always forces the exception type configured
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java
index cc054f4..af8ef8a 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyTest.java
@@ -38,17 +38,17 @@ import org.junit.Test;
 public class DefaultExceptionPolicyStrategyTest extends Assert {
 
     private DefaultExceptionPolicyStrategy strategy;
-    private HashMap<ExceptionPolicyKey, OnExceptionDefinition> policies;
-    private OnExceptionDefinition type1;
-    private OnExceptionDefinition type2;
-    private OnExceptionDefinition type3;
+    private HashMap<ExceptionPolicyKey, ExceptionPolicy> policies;
+    private ExceptionPolicy type1;
+    private ExceptionPolicy type2;
+    private ExceptionPolicy type3;
 
     private void setupPolicies() {
         strategy = new DefaultExceptionPolicyStrategy();
         policies = new HashMap<>();
-        type1 = new OnExceptionDefinition(CamelExchangeException.class);
-        type2 = new OnExceptionDefinition(Exception.class);
-        type3 = new OnExceptionDefinition(IOException.class);
+        type1 = new ExceptionPolicy(new OnExceptionDefinition(CamelExchangeException.class));
+        type2 = new ExceptionPolicy(new OnExceptionDefinition(Exception.class));
+        type3 = new ExceptionPolicy(new OnExceptionDefinition(IOException.class));
         policies.put(new ExceptionPolicyKey(null, CamelExchangeException.class, null), type1);
         policies.put(new ExceptionPolicyKey(null, Exception.class, null), type2);
         policies.put(new ExceptionPolicyKey(null, IOException.class, null), type3);
@@ -58,8 +58,8 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
         // without the top level exception that can be used as fallback
         strategy = new DefaultExceptionPolicyStrategy();
         policies = new HashMap<>();
-        type1 = new OnExceptionDefinition(CamelExchangeException.class);
-        type3 = new OnExceptionDefinition(IOException.class);
+        type1 = new ExceptionPolicy(new OnExceptionDefinition(CamelExchangeException.class));
+        type3 = new ExceptionPolicy(new OnExceptionDefinition(IOException.class));
         policies.put(new ExceptionPolicyKey(null, CamelExchangeException.class, null), type1);
         policies.put(new ExceptionPolicyKey(null, IOException.class, null), type3);
     }
@@ -67,9 +67,9 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
     private void setupPoliciesCausedBy() {
         strategy = new DefaultExceptionPolicyStrategy();
         policies = new HashMap<>();
-        type1 = new OnExceptionDefinition(FileNotFoundException.class);
-        type2 = new OnExceptionDefinition(ConnectException.class);
-        type3 = new OnExceptionDefinition(IOException.class);
+        type1 = new ExceptionPolicy(new OnExceptionDefinition(FileNotFoundException.class));
+        type2 = new ExceptionPolicy(new OnExceptionDefinition(ConnectException.class));
+        type3 = new ExceptionPolicy(new OnExceptionDefinition(IOException.class));
         policies.put(new ExceptionPolicyKey(null, FileNotFoundException.class, null), type1);
         policies.put(new ExceptionPolicyKey(null, IOException.class, null), type2);
         policies.put(new ExceptionPolicyKey(null, ConnectException.class, null), type3);
@@ -78,28 +78,28 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
     @Test
     public void testDirectMatch1() {
         setupPolicies();
-        OnExceptionDefinition result = strategy.getExceptionPolicy(policies, null, new CamelExchangeException("", null));
+        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new CamelExchangeException("", null));
         assertEquals(type1, result);
     }
 
     @Test
     public void testDirectMatch2() {
         setupPolicies();
-        OnExceptionDefinition result = strategy.getExceptionPolicy(policies, null, new Exception(""));
+        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new Exception(""));
         assertEquals(type2, result);
     }
 
     @Test
     public void testDirectMatch3() {
         setupPolicies();
-        OnExceptionDefinition result = strategy.getExceptionPolicy(policies, null, new IOException(""));
+        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new IOException(""));
         assertEquals(type3, result);
     }
 
     @Test
     public void testClosetMatch3() {
         setupPolicies();
-        OnExceptionDefinition result = strategy.getExceptionPolicy(policies, null, new ConnectException(""));
+        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new ConnectException(""));
         assertEquals(type3, result);
 
         result = strategy.getExceptionPolicy(policies, null, new SocketException(""));
@@ -112,7 +112,7 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
     @Test
     public void testClosetMatch2() {
         setupPolicies();
-        OnExceptionDefinition result = strategy.getExceptionPolicy(policies, null, new ClassCastException(""));
+        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new ClassCastException(""));
         assertEquals(type2, result);
 
         result = strategy.getExceptionPolicy(policies, null, new NumberFormatException(""));
@@ -125,7 +125,7 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
     @Test
     public void testClosetMatch1() {
         setupPolicies();
-        OnExceptionDefinition result = strategy.getExceptionPolicy(policies, null, new ValidationException(null, ""));
+        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new ValidationException(null, ""));
         assertEquals(type1, result);
 
         result = strategy.getExceptionPolicy(policies, null, new ExchangeTimedOutException(null, 0));
@@ -135,14 +135,14 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
     @Test
     public void testNoMatch1ThenMatchingJustException() {
         setupPolicies();
-        OnExceptionDefinition result = strategy.getExceptionPolicy(policies, null, new AlreadyStoppedException());
+        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new AlreadyStoppedException());
         assertEquals(type2, result);
     }
 
     @Test
     public void testNoMatch1ThenNull() {
         setupPoliciesNoTopLevelException();
-        OnExceptionDefinition result = strategy.getExceptionPolicy(policies, null, new AlreadyStoppedException());
+        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new AlreadyStoppedException());
         assertNull("Should not find an exception policy to use", result);
     }
 
@@ -152,7 +152,7 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
 
         IOException ioe = new IOException("Damm");
         ioe.initCause(new FileNotFoundException("Somefile not found"));
-        OnExceptionDefinition result = strategy.getExceptionPolicy(policies, null, ioe);
+        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, ioe);
         assertEquals(type1, result);
     }
 
@@ -162,7 +162,7 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
 
         IOException ioe = new IOException("Damm");
         ioe.initCause(new FileNotFoundException("Somefile not found"));
-        OnExceptionDefinition result = strategy.getExceptionPolicy(policies, null, new RuntimeCamelException(ioe));
+        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, new RuntimeCamelException(ioe));
         assertEquals(type1, result);
     }
 
@@ -172,7 +172,7 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
 
         IOException ioe = new IOException("Damm");
         ioe.initCause(new ConnectException("Not connected"));
-        OnExceptionDefinition result = strategy.getExceptionPolicy(policies, null, ioe);
+        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, ioe);
         assertEquals(type3, result);
     }
 
@@ -182,7 +182,7 @@ public class DefaultExceptionPolicyStrategyTest extends Assert {
 
         IOException ioe = new IOException("Damm");
         ioe.initCause(new MalformedURLException("Bad url"));
-        OnExceptionDefinition result = strategy.getExceptionPolicy(policies, null, ioe);
+        ExceptionPolicy result = strategy.getExceptionPolicy(policies, null, ioe);
         assertEquals(type2, result);
     }