This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/master by this push:
new fc3410f CAMEL-15116: Fixed examples on error handler docs.
fc3410f is described below
commit fc3410fe03e7a11d7f4904fcd588bfb1d66796e6
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Jun 11 10:29:56 2020 +0200
CAMEL-15116: Fixed examples on error handler docs.
---
.../modules/ROOT/pages/exception-clause.adoc | 545 +++++++++++++++++++--
1 file changed, 494 insertions(+), 51 deletions(-)
diff --git a/docs/user-manual/modules/ROOT/pages/exception-clause.adoc
b/docs/user-manual/modules/ROOT/pages/exception-clause.adoc
index 97f252c..35474cb 100644
--- a/docs/user-manual/modules/ROOT/pages/exception-clause.adoc
+++ b/docs/user-manual/modules/ROOT/pages/exception-clause.adoc
@@ -233,8 +233,6 @@ Will retry from *`processor2`* - not the complete route.
[[ExceptionClause-ReusingRedeliveryPolicy]]
== Reusing RedeliveryPolicy
-*Since Camel 1.5.1 or later*
-
You can reference a *`RedeliveryPolicy`* so you can reuse existing
configurations and use standard spring bean style configuration that
supports property placeholders.
@@ -256,8 +254,6 @@ supports property placeholders.
[[ExceptionClause-AsynchronousDelayedRedelivery]]
== Asynchronous Delayed Redelivery
-*Since Camel 2.4*
-
From *Camel 2.4*: Camel has a feature to *not block* while waiting for a
delayed redelivery to occur. However if you use transacted routes then
Camel will block as its mandated by the transaction manager to execute
@@ -276,10 +272,7 @@ control pool settings.
[[ExceptionClause-CatchingMultipleExceptions]]
== Catching Multiple Exceptions
-*Since Camel 1.5*
-
-In Camel 1.5 the *exception* clauses has been renamed to *`onException`*
-and it also supports multiple exception classes:
+Multiple exception can be caught as shown:
[source,java]
----
@@ -288,7 +281,7 @@ onException(MyBusinessException.class,
MyOtherBusinessException.class)
.to("activemq:businessFailed");
----
-And in Spring DSL you just add another exception element:
+And in XML DSL you just add another exception element:
[source,xml]
----
@@ -306,7 +299,14 @@ And in Spring DSL you just add another exception element:
We want to handle certain exceptions specially so we add
a *`onException`* clause for that exception.
-/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionProcessorInspectCausedExceptionTest.java
+[source,java]
+----
+// here we register exception cause for MyFunctionException
+// when this exception occur we want it to be processed by our
+// processor
+onException(MyFunctionalException.class).process(new
MyFunctionFailureHandler()).stop();
+----
+
So what happens is that whenever a *`MyFunctionalException`* is thrown it
is being routed to our processor *`MyFunctionFailureHandler`*. So you
@@ -319,7 +319,28 @@ attempted. In our processor we need to determine what to
do. Camel
regards the Exchange as *failure handled*. So our processor is the end
of the route. So lets look the code for our processor.
-/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionProcessorInspectCausedExceptionTest.java
+[source,java]
+----
+ public static class MyFunctionFailureHandler implements Processor {
+
+ @Override
+ public void process(Exchange exchange) throws Exception {
+ // the caused by exception is stored in a property on the exchange
+ Throwable caused = exchange.getProperty(Exchange.EXCEPTION_CAUGHT,
Throwable.class);
+ assertNotNull(caused);
+ // here you can do what you want, but Camel regard this exception
as
+ // handled, and
+ // this processor as a failurehandler, so it wont do redeliveries.
+ // So this is the
+ // end of this route. But if we want to route it somewhere we can
+ // just get a
+ // producer template and send it.
+
+ // send it to our mock endpoint
+
exchange.getContext().createProducerTemplate().send("mock:myerror", exchange);
+ }
+ }
+----
Notice how we get the *caused by* exception using a property on the Exchange.
This is where Camel stores any caught exception during processing. So
@@ -330,10 +351,6 @@ using a producer template from Exchange.
[[ExceptionClause-MarkingExceptionsasHandled]]
== Marking Exceptions as Handled
-*Since Camel 1.5*
-
-== Continued
-
See also the section xref:exception-clause.adoc[Handle and continue
exceptions] below.
Using *`onException`* to handle known exceptions is a very powerful
@@ -367,17 +384,99 @@ In this route below we want to do special handling of
all *`OrderFailedException`* as we want to return a customized response
to the caller. First we setup our routing as:
-/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelHandledExampleTest.java
+[source,java]
+----
+ // we do special error handling for when OrderFailedException is
+ // thrown
+ onException(OrderFailedException.class)
+ // we mark the exchange as handled so the caller doesn't
+ // receive the
+ // OrderFailedException but whatever we want to return
+ // instead
+ .handled(true)
+ // this bean handles the error handling where we can
+ // customize the error
+ // response using java code
+ .bean(OrderService.class, "orderFailed")
+ // and since this is an unit test we use mocks for testing
+ .to("mock:error");
+
+ // this is just the generic error handler where we set the
+ // destination
+ // and the number of redeliveries we want to try
+ errorHandler(deadLetterChannel("mock:error").maximumRedeliveries(1));
+
+ // this is our route where we handle orders
+ from("direct:start")
+ // this bean is our order service
+ .bean(OrderService.class, "handleOrder")
+ // this is the destination if the order is OK
+ .to("mock:result");
+----
Then we have our service beans that is just plain POJO demonstrating how you
can use xref:bean-integration.adoc[Bean Integration] in Camel to avoid
being tied to the Camel API:
-/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelHandledExampleTest.java
+[source,java]
+----
+ /**
+ * Order service as a plain POJO class
+ */
+ public static class OrderService {
+
+ /**
+ * This method handle our order input and return the order
+ *
+ * @param headers the in headers
+ * @param payload the in payload
+ * @return the out payload
+ * @throws OrderFailedException is thrown if the order cannot be
+ * processed
+ */
+ public Object handleOrder(@Headers Map headers, @Body String payload)
throws OrderFailedException {
+ headers.put("customerid", headers.get("customerid"));
+ if ("Order: kaboom".equals(payload)) {
+ throw new OrderFailedException("Cannot order: kaboom");
+ } else {
+ headers.put("orderid", "123");
+ return "Order OK";
+ }
+ }
+
+ /**
+ * This method creates the response to the caller if the order could
not
+ * be processed
+ *
+ * @param headers the in headers
+ * @param payload the in payload
+ * @return the out payload
+ */
+ public Object orderFailed(@Headers Map headers, @Body String payload) {
+ headers.put("customerid", headers.get("customerid"));
+ headers.put("orderid", "failed");
+ return "Order ERROR";
+ }
+ }
+----
And finally the exception that is being thrown is just a regular exception:
-/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelHandledExampleTest.java
+[source,java]
+----
+ /**
+ * Exception thrown if the order cannot be processed
+ */
+ public static class OrderFailedException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public OrderFailedException(String message) {
+ super(message);
+ }
+
+ }
+----
So what happens?
@@ -398,7 +497,47 @@ caller receives an Exchange with the payload *`Order
ERROR`* and a
The same route as above in Spring DSL:
-/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/onexception/deadLetterChannelHandledExampleTest.xml
+[source,xml]
+----
+ <!-- setup our error handler as the deal letter channel -->
+<bean id="errorHandler"
class="org.apache.camel.builder.DeadLetterChannelBuilder">
+ <property name="deadLetterUri" value="mock:error"/>
+</bean>
+
+<!-- this is our POJO bean with our business logic defined as a plain spring
bean -->
+<bean id="orderService"
class="org.apache.camel.spring.processor.onexception.OrderService" />
+
+<!-- this is the camel context where we define the routes -->
+<!-- define our error handler as a global error handler -->
+<camelContext errorHandlerRef="errorHandler"
xmlns="http://camel.apache.org/schema/spring">
+
+ <onException>
+ <!-- the exception is full qualified names as plain strings -->
+ <!-- there can be more just add a 2nd, 3rd exception element (unbounded)
-->
+
<exception>org.apache.camel.spring.processor.onexception.OrderFailedException</exception>
+ <!-- we can set the redelivery policy here as well -->
+ <redeliveryPolicy maximumRedeliveries="1" />
+ <!-- mark this as handled -->
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <!-- let our order service handle this exception, call the orderFailed
method -->
+ <bean ref="orderService" method="orderFailed" />
+ <!-- and since this is a unit test we use mock for assertions -->
+ <to uri="mock:error" />
+ </onException>
+
+ <route>
+ <!-- the route -->
+ <from uri="direct:start" />
+ <!-- in the normal route then route to our order service and call
handleOrder method -->
+ <bean ref="orderService" method="handleOrder" />
+ <!-- and since this is a unit test we use mock for assertions -->
+ <to uri="mock:result" />
+ </route>
+
+</camelContext>
+----
[[ExceptionClause-HandlingandSendingaFixedResponseBacktotheClient]]
== Handling and Sending a Fixed Response Back to the Client
@@ -410,17 +549,40 @@ do as you do in normal Camel routing, use
xref:{eip-vc}:eips:message-translator.adoc[transform] to set the response, as
shown in
the sample below:
-/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionHandleAndTransformTest.java
+[source,java]
+----
+// we catch MyFunctionalException and want to mark it as handled
+// (= no failure returned to client)
+// but we want to return a fixed text response, so we transform
+// OUT body as Sorry.
+onException(MyFunctionalException.class).handled(true).transform().constant("Sorry");
+----
We modify the sample slightly to return the original caused exception
message instead of the fixed text `Sorry`:
-/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionHandleAndTransformTest.java
+[source,java]
+----
+// we catch MyFunctionalException and want to mark it as handled
+// (= no failure returned to client)
+// but we want to return a fixed text response, so we transform
+// OUT body and return the exception message
+onException(MyFunctionalException.class).handled(true).transform(exceptionMessage());
+----
And we can use the xref:components:languages:simple-language.adoc[Simple]
language to set a readable error
message with the caused exception message:
-/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionHandleAndTransformTest.java
+[source,java]
+----
+// we catch MyFunctionalException and want to mark it as handled
+// (= no failure returned to client)
+// but we want to return a fixed text response, so we transform
+// OUT body and return a nice message
+// using the simple language where we want insert the exception
+// message
+onException(MyFunctionalException.class).handled(true).transform().simple("Error
reported: ${exception.message} - cannot process this message.");
+----
[[ExceptionClause-HandleandContinueExceptions]]
== Handle and Continue Exceptions
@@ -452,11 +614,34 @@ use case.
In this route below we want to do special handling of
all *`IllegalArgumentException`* as we just want to continue routing.
-/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionContinueTest.java
+[source,java]
+----
+onException(IllegalArgumentException.class).continued(true);
+
+from("direct:start").to("mock:start").throwException(new
IllegalArgumentException("Forced")).to("mock:result");
+----
And the same example in Spring XML:
-/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/onexception/OnExceptionContinueTest.xml
+[source,xml]
+----
+ <camelContext xmlns="http://camel.apache.org/schema/spring">
+
+ <onException>
+ <exception>java.lang.IllegalArgumentException</exception>
+ <!-- tell Camel to handle and continue when this exception was
thrown -->
+ <continued><constant>true</constant></continued>
+ </onException>
+
+ <route>
+ <from uri="direct:start"/>
+ <to uri="mock:start"/>
+ <throwException ref="forced"/>
+ <to uri="mock:result"/>
+ </route>
+
+ </camelContext>
+----
[[ExceptionClause-WhatistheDifferenceBetweenHandledandContinued?]]
== What is the Difference Between Handled and Continued?
@@ -571,17 +756,38 @@ will handle the exception and use the original message
body and the headers from
[[ExceptionClause-UsingGlobalandPerRouteExceptionClauses]]
== Using Global and Per Route Exception Clauses
-Camel supports quite advanced configuration of exception clauses.
+Camel supports advanced configuration of exception clauses.
You can define exception clauses either as:
* global
* or route specific
-We start off with the sample sample that we change over time. First off
+We start off with the sample that we change over time. First off
we use only global exception clauses:
-/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionRouteTest.java
+[source,java]
+----
+// default should errors go to mock:error
+errorHandler(deadLetterChannel("mock:error").redeliveryDelay(0));
+
+// if a MyTechnicalException is thrown we will not try to
+// redeliver and we mark it as handled
+// so the caller does not get a failure
+// since we have no to then the exchange will continue to be
+// routed to the normal error handler
+// destination that is mock:error as defined above
+onException(MyTechnicalException.class).maximumRedeliveries(0).handled(true);
+
+// if a MyFunctionalException is thrown we do not want Camel to
+// redelivery but handle it our self using
+// our bean myOwnHandler, then the exchange is not routed to the
+// default error (mock:error)
+onException(MyFunctionalException.class).maximumRedeliveries(0).handled(true).to("bean:myOwnHandler");
+
+// here we route message to our service bean
+from("direct:start").choice().when().xpath("//type =
'myType'").to("bean:myServiceBean").end().to("mock:result");
+----
In the next sample we change the global exception policies to be pure route
specific.
@@ -592,12 +798,64 @@ specific.
*`.end()`* to indicate where it stops and when the regular route
continues.
-/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionSubRouteTest.java
+[source,java]
+----
+// default should errors go to mock:error
+errorHandler(deadLetterChannel("mock:error"));
+
+// here we start the routing with the consumer
+from("direct:start")
+
+ // if a MyTechnicalException is thrown we will not try to
+ // redeliver and we mark it as handled
+ // so the caller does not get a failure
+ // since we have no to then the exchange will continue to be
+ // routed to the normal error handler
+ // destination that is mock:error as defined above
+ // we MUST use .end() to indicate that this sub block is
+ // ended
+
.onException(MyTechnicalException.class).maximumRedeliveries(0).handled(true).end()
+
+ // if a MyFunctionalException is thrown we do not want Camel
+ // to redelivery but handle it our self using
+ // our bean myOwnHandler, then the exchange is not routed to
+ // the default error (mock:error)
+ // we MUST use .end() to indicate that this sub block is
+ // ended
+
.onException(MyFunctionalException.class).maximumRedeliveries(0).handled(true).to("bean:myOwnHandler").end()
+
+ // here we have the regular routing
+ .choice().when().xpath("//type =
'myType'").to("bean:myServiceBean").end().to("mock:result");
+----
And now it gets complex as we combine global and route specific exception
policies as we introduce a second route in the sample:
-/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionComplexRouteTest.java
+[source,java]
+----
+// global error handler
+// as its based on a unit test we do not have any delays between
+// and do not log the stack trace
+errorHandler(deadLetterChannel("mock:error").redeliveryDelay(0).logStackTrace(false));
+
+// shared for both routes
+onException(MyTechnicalException.class).handled(true).maximumRedeliveries(2).to("mock:tech.error");
+
+from("direct:start")
+ // route specific on exception for MyFunctionalException
+ // we MUST use .end() to indicate that this sub block is
+ // ended
+
.onException(MyFunctionalException.class).maximumRedeliveries(0).end().to("bean:myServiceBean").to("mock:result");
+
+from("direct:start2")
+ // route specific on exception for MyFunctionalException
+ // that is different than the previous route
+ // here we marked it as handled and send it to a different
+ // destination mock:handled
+ // we MUST use .end() to indicate that this sub block is
+ // ended
+
.onException(MyFunctionalException.class).handled(true).maximumRedeliveries(0).to("mock:handled").end().to("bean:myServiceBean").to("mock:result");
+----
Notice that we can define the same exception *`MyFunctionalException`* in both
routes, but they are configured differently and thus is handled
@@ -608,7 +866,22 @@ exception policy.
And finally we top this by throwing in a nested error handler as well,
as we add the 3rd route shown below:
-/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionComplexWithNestedErrorHandlerRouteTest.java
+[source,java]
+----
+from("direct:start3")
+ // route specific error handler that is different than the
+ // global error handler
+ // here we do not redeliver and send errors to mock:error3
+ // instead of the global endpoint
+ .errorHandler(deadLetterChannel("mock:error3").maximumRedeliveries(0))
+
+ // route specific on exception to mark MyFunctionalException
+ // as being handled
+ .onException(MyFunctionalException.class).handled(true).end()
+ // however we want the IO exceptions to redeliver at most 3
+ // times
+
.onException(IOException.class).maximumRedeliveries(3).end().to("bean:myServiceBean").to("mock:result");
+----
=== Global exception policies and nested error handlers
@@ -622,14 +895,30 @@ that is selected.
[[ExceptionClause-UsingFineGrainedSelectionUsingonWhenPredicate]]
== Using Fine Grained Selection Using `onWhen` Predicate
-*Since Camel 1.5.1 or later*
-
You can attach an xref:expression.adoc[Expression] to the exception
clause to have fine grained control when a clause should be selected or
not. As it's an xref:expression.adoc[Expression] you can use any kind of
code to perform the test. Here is a sample:
-/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategyUsingWhenTest.java
+[source,java]
+----
+errorHandler(deadLetterChannel("mock:error").redeliveryDelay(0).maximumRedeliveries(3));
+
+// here we define our onException to catch MyUserException when
+// there is a header[user] on the exchange that is not null
+onException(MyUserException.class).onWhen(header("user").isNotNull()).maximumRedeliveries(1)
+ // setting delay to zero is just to make unit testing faster
+ .redeliveryDelay(0).to(ERROR_USER_QUEUE);
+
+// here we define onException to catch MyUserException as a kind
+// of fallback when the above did not match.
+// Notice: The order how we have defined these onException is
+// important as Camel will resolve in the same order as they
+// have been defined
+onException(MyUserException.class).maximumRedeliveries(2)
+ // setting delay to zero is just to make unit testing faster
+ .redeliveryDelay(0).to(ERROR_QUEUE);
+----
In the sample above we have two *`onException`*'s defined. The first has
an *`onWhen`* expression attached to only trigger if the message has a
@@ -647,8 +936,6 @@ default error handler will kick in.
[[ExceptionClause-UsingonRedeliveryProcessor]]
== Using `onRedelivery` Processor
-*Since Camel 2.0*
-
xref:{eip-vc}:eips:dead-letter-channel.adoc[Dead Letter Channel] has support
for *`onRedelivery`* to allow custom processing of a Message before its
being redelivered. It can be used to add some customer header or
@@ -665,12 +952,40 @@ In the code below we want to do some custom code before
redelivering any
the *`IOException`* and set the *`onRedelivery`* to use our custom
processor:
-/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelOnExceptionOnRedeliveryTest.java
+[source,java]
+----
+// when we redeliver caused by an IOException we want to do some
+// special code before the redeliver attempt
+onException(IOException.class)
+ // try to redeliver at most 3 times
+ .maximumRedeliveries(3)
+ // setting delay to zero is just to make unit testing faster
+ .redeliveryDelay(0).onRedelivery(new MyIORedeliverProcessor());
+----
And in our custom processor we set a special timeout header to the message.
You can of course do anything what you like in your code.
-/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelOnExceptionOnRedeliveryTest.java
+[source,java]
+----
+// This is our processor that is executed before every redelivery attempt
+// here we can do what we want in the java code, such as altering the
+// message
+public static class MyRedeliverProcessor implements Processor {
+
+ @Override
+ public void process(Exchange exchange) throws Exception {
+ // the message is being redelivered so we can alter it
+
+ // we just append the redelivery counter to the body
+ // you can of course do all kind of stuff instead
+ String body = exchange.getIn().getBody(String.class);
+ int count = exchange.getIn().getHeader("CamelRedeliveryCounter",
Integer.class);
+
+ exchange.getIn().setBody(body + count);
+ }
+}
+----
[[ExceptionClause-UsingonRedeliveryinSpringDSL]]
== Using `onRedelivery` in Spring DSL
@@ -678,12 +993,21 @@ You can of course do anything what you like in your code.
In Spring DSL you need to use the *`onRedeliveryRef`* attribute to refer
to a spring bean id that is your custom processor:
-/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/onexception/DeadLetterChannelOnExceptionOnRedeliveryTest.xml
+[source,xml]
+----
+<onException onRedeliveryRef="myIORedeliverProcessor">
+ <exception>java.io.IOException</exception>
+</onException>
+----
And our processor is just a regular spring bean (we use *`$`* for the inner
class as this code is based on unit testing):
-/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/onexception/DeadLetterChannelOnExceptionOnRedeliveryTest.xml
+[source,xml]
+----
+ <bean id="myRedeliveryProcessor"
+
class="org.apache.camel.processor.DeadLetterChannelOnExceptionOnRedeliveryTest$MyRedeliverProcessor"/>
+----
[[ExceptionClause-UsingonExceptionOccurredProcessor]]
== Using `onExceptionOccurred` Processor
@@ -743,8 +1067,6 @@ to refer to a spring bean id that is your custom processor:
[[ExceptionClause-UsingFineGrainedRetryUsingretryWhilePredicate]]
== Using Fine Grained Retry Using `retryWhile` Predicate
-*Since Camel 2.0*
-
=== RetryUntil
In Camel 2.0 to 2.3 its called *`retryUntil`*. From *Camel 2.4*: its
@@ -757,32 +1079,72 @@ redeliver until the predicate returns false.
Example:
-/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionRetryUntilTest.java
+[source,java]
+----
+// we want to use a predicate for retries so we can determine in
+// our bean when retry should stop, notice it will overrule the global
+// error handler where we defined at most 1 redelivery attempt. Here we will
+// continue until the predicate returns false
+onException(MyFunctionalException.class).retryWhile(method("myRetryHandler")).handled(true).transform().constant("Sorry");
+----
Where the bean *`myRetryHandler`* is computing if we should retry or not:
-/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionRetryUntilTest.java
+[source,java]
+----
+public class MyRetryBean {
+
+ // using bean binding we can bind the information from the exchange to
+ // the types we have in our method signature
+ public boolean retry(@Header(Exchange.REDELIVERY_COUNTER) Integer counter,
@Body String body, @ExchangeException Exception causedBy) {
+ // NOTE: counter is the redelivery attempt, will start from 1
+ invoked++;
+
+ assertEquals("Hello World", body);
+ boolean b = causedBy instanceof MyFunctionalException;
+ assertTrue(b);
+
+ // we can of course do what ever we want to determine the result but
+ // this is a unit test so we end after 3 attempts
+ return counter < 3;
+ }
+}
+----
[[ExceptionClause-UsingCustomExceptionPolicyStrategy]]
== Using Custom `ExceptionPolicyStrategy`
-*Available in Camel 1.4*
-
The default
https://www.javadoc.io/doc/org.apache.camel/camel-base/current/org/apache/camel/processor/errorhandler/ExceptionPolicyStrategy.html[ExceptionPolicyStrategy]
in Camel should be sufficient in nearly all use-cases (see section
xref:exception-clause.adoc#ExceptionClause-HowDoesCamelSelectWhichClauseShouldHandleaGivenThrownException[How
does Camel select which clause should handle a given thrown Exception]).
-However, if you need to use your own this can be configured as the
+However, if you need to use your own (use only for rare and advanced
use-cases) this can be configured as the
sample below illustrates:
-/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
+[source,java]
+----
+// configure the error handler to use my policy instead of the default from
Camel
+errorHandler(deadLetterChannel("mock:error").exceptionPolicyStrategy(new
MyPolicy()));
+----
Using our own strategy *`MyPolicy`* we can change the default behavior of
Camel with our own code to resolve which
http://camel.apache.org/maven/camel-core/apidocs/org/apache/camel/model/ExceptionType.html[ExceptionType]
from above should be handling the given thrown exception.
-/camel-core/src/test/java/org/apache/camel/processor/exceptionpolicy/CustomExceptionPolicyStrategyTest.java
+[source,java]
+----
+public static class MyPolicy implements ExceptionPolicyStrategy {
+
+ @Override
+ 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 new ExceptionPolicyKey(null, MyPolicyException.class, null);
+ }
+}
+----
[[ExceptionClause-UsingtheExceptionClauseinSpringDSL]]
== Using the Exception Clause in Spring DSL
@@ -790,9 +1152,90 @@ from above should be handling the given thrown exception.
You can use all of the above mentioned exception clause features in the
Spring DSL as well. Here are a few examples:
-* Global scoped - *Available in Camel 2.0*
-/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/onexception/deadLetterChannelHandledExampleTest.xml
+* Global scoped
+
+[source,xml]
+----
+<!-- setup our error handler as the deal letter channel -->
+<bean id="errorHandler"
class="org.apache.camel.builder.DeadLetterChannelBuilder">
+ <property name="deadLetterUri" value="mock:error"/>
+</bean>
+
+<!-- this is our POJO bean with our business logic defined as a plain spring
bean -->
+<bean id="orderService"
class="org.apache.camel.spring.processor.onexception.OrderService" />
+
+<!-- this is the camel context where we define the routes -->
+<!-- define our error handler as a global error handler -->
+<camelContext errorHandlerRef="errorHandler"
xmlns="http://camel.apache.org/schema/spring">
+
+ <onException>
+ <!-- the exception is full qualified names as plain strings -->
+ <!-- there can be more just add a 2nd, 3rd exception element (unbounded)
-->
+
<exception>org.apache.camel.spring.processor.onexception.OrderFailedException</exception>
+ <!-- we can set the redelivery policy here as well -->
+ <redeliveryPolicy maximumRedeliveries="1" />
+ <!-- mark this as handled -->
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <!-- let our order service handle this exception, call the orderFailed
method -->
+ <bean ref="orderService" method="orderFailed" />
+ <!-- and since this is a unit test we use mock for assertions -->
+ <to uri="mock:error" />
+ </onException>
+
+ <route>
+ <!-- the route -->
+ <from uri="direct:start" />
+ <!-- in the normal route then route to our order service and call
handleOrder method -->
+ <bean ref="orderService" method="handleOrder" />
+ <!-- and since this is a unit test we use mock for assertions -->
+ <to uri="mock:result" />
+ </route>
+
+</camelContext>
+----
* Route specific scoped
-/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/onexception/onExceptionSubRouteTest.xml
+
+[source,xml]
+----
+<!-- setup our error handler as the deal letter channel -->
+<bean id="deadLetter"
class="org.apache.camel.builder.DeadLetterChannelBuilder">
+ <property name="deadLetterUri" value="mock:dead"/>
+</bean>
+
+<!-- the default error handler used in the 2nd route -->
+<bean id="defaultErrorHandler"
class="org.apache.camel.builder.DefaultErrorHandlerBuilder"/>
+
+<!-- this is our POJO bean with our business logic defined as a plain spring
bean -->
+<bean id="orderService"
class="org.apache.camel.spring.processor.onexception.OrderService"/>
+
+<!-- this is the camel context where we define the routes -->
+<camelContext xmlns="http://camel.apache.org/schema/spring">
+
+ <route errorHandlerRef="deadLetter">
+ <from uri="direct:start"/>
+ <onException>
+
<exception>org.apache.camel.spring.processor.onexception.OrderFailedException</exception>
+ <redeliveryPolicy maximumRedeliveries="1"/>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <bean ref="orderService" method="orderFailed"/>
+ <to uri="mock:error"/>
+ </onException>
+ <bean ref="orderService" method="handleOrder"/>
+ <to uri="mock:result"/>
+ </route>
+
+ <!-- The exception clause specified in the first route will not be used in
this route -->
+ <route errorHandlerRef="defaultErrorHandler">
+ <from uri="direct:start_with_no_handler"/>
+ <bean ref="orderService" method="handleOrder"/>
+ <to uri="mock:result"/>
+ </route>
+
+</camelContext>
+----