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:55 UTC

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

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