Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
Expand Down Expand Up @@ -81,8 +82,6 @@ public class OnExceptionDefinition extends ProcessorDefinition<OnExceptionDefini
@XmlElementRef
private List<ProcessorDefinition<?>> outputs = new ArrayList<>();
@XmlTransient
private List<Class<? extends Throwable>> exceptionClasses;
@XmlTransient
private Predicate handledPolicy;
@XmlTransient
private Predicate continuedPolicy;
Expand All @@ -104,12 +103,11 @@ public OnExceptionDefinition() {
}

public OnExceptionDefinition(List<Class<? extends Throwable>> exceptionClasses) {
this.exceptionClasses = exceptionClasses;
this.exceptions.addAll(exceptionClasses.stream().map(Class::getName).collect(Collectors.toList()));
}

public OnExceptionDefinition(Class<? extends Throwable> exceptionType) {
exceptionClasses = new ArrayList<>();
exceptionClasses.add(exceptionType);
this.exceptions.add(exceptionType.getName());
}

public void setRouteScoped(boolean routeScoped) {
Expand All @@ -127,7 +125,7 @@ public String toString() {
}

protected String description() {
return getExceptionClasses() + (onWhen != null ? " " + onWhen : "");
return getExceptions() + (onWhen != null ? " " + onWhen : "");
}

@Override
Expand Down Expand Up @@ -193,11 +191,6 @@ public void addRoutes(RouteContext routeContext, Collection<Route> routes) throw
setOnRedeliveryFromRedeliveryRef(routeContext);
setOnExceptionOccurredFromOnExceptionOccurredRef(routeContext);

// load exception classes
if (exceptions != null && !exceptions.isEmpty()) {
exceptionClasses = createExceptionClasses(routeContext.getCamelContext().getClassResolver());
}

// must validate configuration before creating processor
validateConfiguration();

Expand All @@ -223,6 +216,7 @@ public void addRoutes(RouteContext routeContext, Collection<Route> routes) throw
@Override
public CatchProcessor createProcessor(RouteContext routeContext) throws Exception {
// load exception classes
List<Class<? extends Throwable>> exceptionClasses = null;
if (exceptions != null && !exceptions.isEmpty()) {
exceptionClasses = createExceptionClasses(routeContext.getCamelContext().getClassResolver());
}
Expand All @@ -247,15 +241,14 @@ public CatchProcessor createProcessor(RouteContext routeContext) throws Exceptio
handle = handled.createPredicate(routeContext);
}

return new CatchProcessor(getExceptionClasses(), childProcessor, when, handle);
return new CatchProcessor(exceptionClasses, childProcessor, when, handle);
}

protected void validateConfiguration() {
if (isInheritErrorHandler() != null && isInheritErrorHandler()) {
throw new IllegalArgumentException(this + " cannot have the inheritErrorHandler option set to true");
}

List<Class<? extends Throwable>> exceptions = getExceptionClasses();
if (exceptions == null || exceptions.isEmpty()) {
throw new IllegalArgumentException("At least one exception must be configured on " + this);
}
Expand Down Expand Up @@ -287,7 +280,7 @@ protected void validateConfiguration() {

@Override
public OnExceptionDefinition onException(Class<? extends Throwable> exceptionType) {
getExceptionClasses().add(exceptionType);
getExceptions().add(exceptionType.getName());
return this;
}

Expand Down Expand Up @@ -868,14 +861,6 @@ public boolean isOutputSupported() {
return true;
}

public List<Class<? extends Throwable>> getExceptionClasses() {
return exceptionClasses;
}

public void setExceptionClasses(List<Class<? extends Throwable>> exceptionClasses) {
this.exceptionClasses = exceptionClasses;
}

public List<String> getExceptions() {
return exceptions;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,21 @@
*/
package org.apache.camel.processor;

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.exceptionpolicy.DefaultExceptionPolicyStrategy;
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;
import org.slf4j.Logger;
Expand All @@ -52,23 +55,40 @@ public void addExceptionPolicy(RouteContext routeContext, OnExceptionDefinition
if (errorHandler != null) {
addChildService(errorHandler);
}
}

List<Class<? extends Throwable>> list = exceptionType.getExceptionClasses();
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();
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);
}
}
ExceptionPolicyKey key = new ExceptionPolicyKey(routeId, clazz, exceptionType.getOnWhen());
exceptionPolicies.put(key, exceptionType);
}
}

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 new RuntimeCamelException(e);
}
}
return answer;
}

/**
* Attempts to find the best suited {@link OnExceptionDefinition} to be used for handling the given thrown exception.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public void testDumpAsXml() throws Exception {
assertTrue(xml.contains("route"));
assertTrue(xml.contains("myRoute"));
assertTrue(xml.contains("mock:result"));
assertTrue(xml.contains("java.lang.Exception"));
}

@Test
Expand Down Expand Up @@ -91,6 +92,8 @@ protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
onException(Exception.class).log("${exception.stacktrace}").logStackTrace(true).handled(true);

from("direct:start").routeId("myRoute")
.log("Got ${body}")
.to("mock:result");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
import java.util.ArrayList;
import java.util.List;

import org.apache.camel.ContextTestSupport;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.OnExceptionDefinition;
import org.junit.Assert;
import org.junit.Test;

public class ErrorHandlerSupportTest extends Assert {
public class ErrorHandlerSupportTest extends ContextTestSupport {

@Test
public void testOnePolicyChildFirst() {
Expand All @@ -34,10 +36,10 @@ public void testOnePolicyChildFirst() {
exceptions.add(ParentException.class);

ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
support.addExceptionPolicy(null, new OnExceptionDefinition(exceptions));
support.addExceptionPolicy(context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(exceptions));

assertEquals(ChildException.class, getExceptionPolicyFor(support, new ChildException(), 0));
assertEquals(ParentException.class, getExceptionPolicyFor(support, new ParentException(), 1));
assertEquals(ChildException.class.getName(), getExceptionPolicyFor(support, new ChildException(), 0));
assertEquals(ParentException.class.getName(), getExceptionPolicyFor(support, new ParentException(), 1));
}

@Test
Expand All @@ -47,35 +49,35 @@ public void testOnePolicyChildLast() {
exceptions.add(ChildException.class);

ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
support.addExceptionPolicy(null, new OnExceptionDefinition(exceptions));
support.addExceptionPolicy(context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(exceptions));

assertEquals(ChildException.class, getExceptionPolicyFor(support, new ChildException(), 1));
assertEquals(ParentException.class, getExceptionPolicyFor(support, new ParentException(), 0));
assertEquals(ChildException.class.getName(), getExceptionPolicyFor(support, new ChildException(), 1));
assertEquals(ParentException.class.getName(), getExceptionPolicyFor(support, new ParentException(), 0));
}

@Test
public void testTwoPolicyChildFirst() {
ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
support.addExceptionPolicy(null, new OnExceptionDefinition(ChildException.class));
support.addExceptionPolicy(null, new OnExceptionDefinition(ParentException.class));
support.addExceptionPolicy(context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(ChildException.class));
support.addExceptionPolicy(context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(ParentException.class));

assertEquals(ChildException.class, getExceptionPolicyFor(support, new ChildException(), 0));
assertEquals(ParentException.class, getExceptionPolicyFor(support, new ParentException(), 0));
assertEquals(ChildException.class.getName(), getExceptionPolicyFor(support, new ChildException(), 0));
assertEquals(ParentException.class.getName(), getExceptionPolicyFor(support, new ParentException(), 0));
}

@Test
public void testTwoPolicyChildLast() {
ErrorHandlerSupport support = new ShuntErrorHandlerSupport();
support.addExceptionPolicy(null, new OnExceptionDefinition(ParentException.class));
support.addExceptionPolicy(null, new OnExceptionDefinition(ChildException.class));
support.addExceptionPolicy(context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(ParentException.class));
support.addExceptionPolicy(context.getRoute("foo").getRouteContext(), new OnExceptionDefinition(ChildException.class));

assertEquals(ChildException.class, getExceptionPolicyFor(support, new ChildException(), 0));
assertEquals(ParentException.class, getExceptionPolicyFor(support, new ParentException(), 0));
assertEquals(ChildException.class.getName(), getExceptionPolicyFor(support, new ChildException(), 0));
assertEquals(ParentException.class.getName(), getExceptionPolicyFor(support, new ParentException(), 0));
}

private static Class<? extends Throwable> getExceptionPolicyFor(ErrorHandlerSupport support, Throwable childException,
private static String getExceptionPolicyFor(ErrorHandlerSupport support, Throwable childException,
int index) {
return support.getExceptionPolicy(null, childException).getExceptionClasses().get(index);
return support.getExceptionPolicy(null, childException).getExceptions().get(index);
}

private static class ParentException extends Exception {
Expand Down Expand Up @@ -106,4 +108,13 @@ public void process(Exchange exchange) throws Exception {
}
}

@Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:foo").to("mock:foo").routeId("foo");
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void configure() throws Exception {
fail("Should have thrown exception");
} catch (FailedToCreateRouteException e) {
IllegalArgumentException iae = assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
assertEquals("OnException[[class java.lang.Exception] -> []] is not configured.", iae.getMessage());
assertEquals("OnException[[java.lang.Exception] -> []] is not configured.", iae.getMessage());
}
}

Expand All @@ -69,7 +69,7 @@ public void configure() throws Exception {
fail("Should have thrown exception");
} catch (FailedToCreateRouteException e) {
IllegalArgumentException iae = assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
assertEquals("OnException[[class java.lang.Exception] -> []] is not configured.", iae.getMessage());
assertEquals("OnException[[java.lang.Exception] -> []] is not configured.", iae.getMessage());
}
}

Expand All @@ -89,7 +89,7 @@ public void configure() throws Exception {
fail("Should have thrown exception");
} catch (FailedToCreateRouteException e) {
IllegalArgumentException iae = assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
assertEquals("OnException[[class java.lang.Exception] -> []] is not configured.", iae.getMessage());
assertEquals("OnException[[java.lang.Exception] -> []] is not configured.", iae.getMessage());
}
}

Expand All @@ -109,7 +109,7 @@ public void configure() throws Exception {
fail("Should have thrown exception");
} catch (FailedToCreateRouteException e) {
IllegalArgumentException iae = assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
assertEquals("OnException[[class java.lang.Exception] -> []] is not configured.", iae.getMessage());
assertEquals("OnException[[java.lang.Exception] -> []] is not configured.", iae.getMessage());
}
}

Expand Down
2 changes: 1 addition & 1 deletion parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5483,7 +5483,7 @@
<!-- lets re-run the failed test one more time, just to be sure -->
<rerunFailingTestsCount>2</rerunFailingTestsCount>
<systemPropertyVariables>
<javax.xml.accessExternalSchema>file,http</javax.xml.accessExternalSchema>
<javax.xml.accessExternalSchema>file,http,https</javax.xml.accessExternalSchema>
<javax.xml.accessExternalDTD>file,http</javax.xml.accessExternalDTD>
<derby.stream.error.file>target/derby.log</derby.stream.error.file>
<java.awt.headless>${java.awt.headless}</java.awt.headless>
Expand Down