You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2009/08/29 09:42:58 UTC

svn commit: r809092 - in /camel/trunk/camel-core/src: main/java/org/apache/camel/management/ main/java/org/apache/camel/management/event/ main/java/org/apache/camel/processor/ main/java/org/apache/camel/spi/ main/java/org/apache/camel/util/ test/java/o...

Author: davsclaus
Date: Sat Aug 29 07:42:57 2009
New Revision: 809092

URL: http://svn.apache.org/viewvc?rev=809092&view=rev
Log:
CAMEL-1933: Overhaul of JMX. Added event for exchange handled  by failure processors such as moved to dead letter channel.

Added:
    camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeFailureHandledEvent.java   (with props)
    camel/trunk/camel-core/src/test/java/org/apache/camel/management/EventNotifierFailreHandledEventsTest.java
      - copied, changed from r809085, camel/trunk/camel-core/src/test/java/org/apache/camel/management/EventNotifierEventsTest.java
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultEventFactory.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStartedEvent.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStartingEvent.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStoppedEvent.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStoppingEvent.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeCompletedEvent.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeCreatedEvent.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeFailedEvent.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/RouteStartedEvent.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/RouteStoppedEvent.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RedeliveryErrorHandler.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/spi/EventFactory.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/util/EventHelper.java

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultEventFactory.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultEventFactory.java?rev=809092&r1=809091&r2=809092&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultEventFactory.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultEventFactory.java Sat Aug 29 07:42:57 2009
@@ -21,6 +21,7 @@
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Route;
+import org.apache.camel.Processor;
 import org.apache.camel.management.event.CamelContextStartedEvent;
 import org.apache.camel.management.event.CamelContextStartingEvent;
 import org.apache.camel.management.event.CamelContextStoppedEvent;
@@ -30,6 +31,7 @@
 import org.apache.camel.management.event.ExchangeFailedEvent;
 import org.apache.camel.management.event.RouteStartedEvent;
 import org.apache.camel.management.event.RouteStoppedEvent;
+import org.apache.camel.management.event.ExchangeFailureHandledEvent;
 import org.apache.camel.spi.EventFactory;
 
 /**
@@ -73,4 +75,7 @@
         return new ExchangeFailedEvent(exchange);
     }
 
+    public EventObject createExchangeFailureHandled(Exchange exchange, Processor failureHandler, boolean deadLetterChannel) {
+        return new ExchangeFailureHandledEvent(exchange, failureHandler, deadLetterChannel);
+    }
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStartedEvent.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStartedEvent.java?rev=809092&r1=809091&r2=809092&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStartedEvent.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStartedEvent.java Sat Aug 29 07:42:57 2009
@@ -25,7 +25,7 @@
  */
 public class CamelContextStartedEvent extends EventObject {
 
-    private CamelContext context;
+    private final CamelContext context;
 
     public CamelContextStartedEvent(CamelContext source) {
         super(source);

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStartingEvent.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStartingEvent.java?rev=809092&r1=809091&r2=809092&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStartingEvent.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStartingEvent.java Sat Aug 29 07:42:57 2009
@@ -25,7 +25,7 @@
  */
 public class CamelContextStartingEvent extends EventObject {
 
-    private CamelContext context;
+    private final CamelContext context;
 
     public CamelContextStartingEvent(CamelContext source) {
         super(source);

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStoppedEvent.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStoppedEvent.java?rev=809092&r1=809091&r2=809092&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStoppedEvent.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStoppedEvent.java Sat Aug 29 07:42:57 2009
@@ -25,7 +25,7 @@
  */
 public class CamelContextStoppedEvent extends EventObject {
 
-    private CamelContext context;
+    private final CamelContext context;
 
     public CamelContextStoppedEvent(CamelContext source) {
         super(source);

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStoppingEvent.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStoppingEvent.java?rev=809092&r1=809091&r2=809092&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStoppingEvent.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/CamelContextStoppingEvent.java Sat Aug 29 07:42:57 2009
@@ -25,7 +25,7 @@
  */
 public class CamelContextStoppingEvent extends EventObject {
 
-    private CamelContext context;
+    private final CamelContext context;
 
     public CamelContextStoppingEvent(CamelContext source) {
         super(source);

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeCompletedEvent.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeCompletedEvent.java?rev=809092&r1=809091&r2=809092&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeCompletedEvent.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeCompletedEvent.java Sat Aug 29 07:42:57 2009
@@ -25,7 +25,7 @@
  */
 public class ExchangeCompletedEvent extends EventObject {
 
-    private Exchange exchange;
+    private final Exchange exchange;
 
     public ExchangeCompletedEvent(Exchange source) {
         super(source);
@@ -35,4 +35,10 @@
     public Exchange getExchange() {
         return exchange;
     }
+
+    @Override
+    public String toString() {
+        return "Exchange completed: " + exchange;
+    }
+
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeCreatedEvent.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeCreatedEvent.java?rev=809092&r1=809091&r2=809092&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeCreatedEvent.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeCreatedEvent.java Sat Aug 29 07:42:57 2009
@@ -25,7 +25,7 @@
  */
 public class ExchangeCreatedEvent extends EventObject {
 
-    private Exchange exchange;
+    private final Exchange exchange;
 
     public ExchangeCreatedEvent(Exchange source) {
         super(source);
@@ -35,4 +35,10 @@
     public Exchange getExchange() {
         return exchange;
     }
+
+    @Override
+    public String toString() {
+        return "Exchange created: " + exchange;
+    }
+
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeFailedEvent.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeFailedEvent.java?rev=809092&r1=809091&r2=809092&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeFailedEvent.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeFailedEvent.java Sat Aug 29 07:42:57 2009
@@ -25,7 +25,7 @@
  */
 public class ExchangeFailedEvent extends EventObject {
 
-    private Exchange exchange;
+    private final Exchange exchange;
 
     public ExchangeFailedEvent(Exchange source) {
         super(source);
@@ -36,4 +36,9 @@
         return exchange;
     }
 
+    @Override
+    public String toString() {
+        return "Exchange failed: " + exchange;
+    }
+
 }

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeFailureHandledEvent.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeFailureHandledEvent.java?rev=809092&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeFailureHandledEvent.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeFailureHandledEvent.java Sat Aug 29 07:42:57 2009
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.management.event;
+
+import java.util.EventObject;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+
+/**
+ * @version $Revision$
+ */
+public class ExchangeFailureHandledEvent extends EventObject {
+
+    private final Exchange exchange;
+    private final Processor failureHandler;
+    private final boolean deadLetterChannel;
+    private final boolean handled;
+
+    public ExchangeFailureHandledEvent(Exchange source, Processor failureHandler, boolean deadLetterChannel) {
+        super(source);
+        this.exchange = source;
+        this.failureHandler = failureHandler;
+        this.deadLetterChannel = deadLetterChannel;
+        this.handled = exchange.getProperty(Exchange.ERRORHANDLER_HANDLED, Boolean.class);
+    }
+
+    public Exchange getExchange() {
+        return exchange;
+    }
+
+    public Processor getFailureHandler() {
+        return failureHandler;
+    }
+
+    public boolean isDeadLetterChannel() {
+        return deadLetterChannel;
+    }
+
+    public boolean isHandled() {
+        return handled;
+    }
+
+    @Override
+    public String toString() {
+        if (isDeadLetterChannel()) {
+            return "Exchange: " + exchange + (handled ? " handled" : "") + " by dead letter channel: " + failureHandler;
+        } else {
+            return "Exchange: " + exchange + (handled ? " handled" : "") + " by: " + failureHandler;
+        }
+    }
+
+}

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeFailureHandledEvent.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/ExchangeFailureHandledEvent.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/RouteStartedEvent.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/RouteStartedEvent.java?rev=809092&r1=809091&r2=809092&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/RouteStartedEvent.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/RouteStartedEvent.java Sat Aug 29 07:42:57 2009
@@ -25,7 +25,7 @@
  */
 public class RouteStartedEvent extends EventObject {
 
-    private Route route;
+    private final Route route;
 
     public RouteStartedEvent(Route source) {
         super(source);
@@ -35,4 +35,10 @@
     public Route getRoute() {
         return route;
     }
+
+    @Override
+    public String toString() {
+        return "Started route: " + route.getId();
+    }
+
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/RouteStoppedEvent.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/RouteStoppedEvent.java?rev=809092&r1=809091&r2=809092&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/RouteStoppedEvent.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/event/RouteStoppedEvent.java Sat Aug 29 07:42:57 2009
@@ -25,7 +25,7 @@
  */
 public class RouteStoppedEvent extends EventObject {
 
-    private Route route;
+    private final Route route;
 
     public RouteStoppedEvent(Route source) {
         super(source);
@@ -36,4 +36,9 @@
         return route;
     }
 
+    @Override
+    public String toString() {
+        return "Stopped route: " + route.getId();
+    }
+
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RedeliveryErrorHandler.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RedeliveryErrorHandler.java?rev=809092&r1=809091&r2=809092&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RedeliveryErrorHandler.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RedeliveryErrorHandler.java Sat Aug 29 07:42:57 2009
@@ -27,6 +27,7 @@
 import org.apache.camel.util.ExchangeHelper;
 import org.apache.camel.util.MessageHelper;
 import org.apache.camel.util.ServiceHelper;
+import org.apache.camel.util.EventHelper;
 
 /**
  * Base redeliverable error handler that also supports a final dead letter queue in case
@@ -129,6 +130,11 @@
                 deliverToFailureProcessor(target, exchange, data);
                 // prepare the exchange for failure before returning
                 prepareExchangeAfterFailure(exchange, data);
+                // fire event if we had a failure processor to handle it
+                if (target != null) {
+                    boolean deadLetterChannel = target == data.deadLetterProcessor && data.deadLetterProcessor != null;
+                    EventHelper.notifyExchangeFailureHandled(exchange.getContext(), exchange, target, deadLetterChannel);
+                }
                 // and then return
                 return;
             }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/spi/EventFactory.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/spi/EventFactory.java?rev=809092&r1=809091&r2=809092&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/spi/EventFactory.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/spi/EventFactory.java Sat Aug 29 07:42:57 2009
@@ -21,6 +21,7 @@
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Route;
+import org.apache.camel.Processor;
 
 /**
  * Factory to create {@link java.util.EventObject} events} that are emitted when such an event occur.
@@ -49,4 +50,6 @@
 
     EventObject createExchangeFailedEvent(Exchange exchange);
 
+    EventObject createExchangeFailureHandled(Exchange exchange, Processor failureHandler, boolean deadLetterChannel);
+
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/EventHelper.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/EventHelper.java?rev=809092&r1=809091&r2=809092&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/util/EventHelper.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/EventHelper.java Sat Aug 29 07:42:57 2009
@@ -20,6 +20,7 @@
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
 import org.apache.camel.Route;
 import org.apache.camel.spi.EventFactory;
 import org.apache.camel.spi.EventNotifier;
@@ -182,6 +183,23 @@
         doNotifyEvent(notifier, event);
     }
 
+    public static void notifyExchangeFailureHandled(CamelContext context, Exchange exchange, Processor failureHandler,
+                                                    boolean deadLetterChannel) {
+        EventNotifier notifier = context.getManagementStrategy().getEventNotifier();
+        if (notifier == null) {
+            return;
+        }
+        EventFactory factory = context.getManagementStrategy().getEventFactory();
+        if (factory == null) {
+            return;
+        }
+        EventObject event = factory.createExchangeFailureHandled(exchange, failureHandler, deadLetterChannel);
+        if (event == null) {
+            return;
+        }
+        doNotifyEvent(notifier, event);
+    }
+
     private static void doNotifyEvent(EventNotifier notifier, EventObject event) {
         if (!notifier.isEnabled(event)) {
             if (LOG.isTraceEnabled()) {

Copied: camel/trunk/camel-core/src/test/java/org/apache/camel/management/EventNotifierFailreHandledEventsTest.java (from r809085, camel/trunk/camel-core/src/test/java/org/apache/camel/management/EventNotifierEventsTest.java)
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/management/EventNotifierFailreHandledEventsTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/management/EventNotifierFailreHandledEventsTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/management/EventNotifierEventsTest.java&r1=809085&r2=809092&rev=809092&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/management/EventNotifierEventsTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/management/EventNotifierFailreHandledEventsTest.java Sat Aug 29 07:42:57 2009
@@ -26,19 +26,17 @@
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.management.event.CamelContextStartedEvent;
 import org.apache.camel.management.event.CamelContextStartingEvent;
-import org.apache.camel.management.event.CamelContextStoppedEvent;
-import org.apache.camel.management.event.CamelContextStoppingEvent;
 import org.apache.camel.management.event.ExchangeCompletedEvent;
 import org.apache.camel.management.event.ExchangeCreatedEvent;
-import org.apache.camel.management.event.ExchangeFailedEvent;
+import org.apache.camel.management.event.ExchangeFailureHandledEvent;
 import org.apache.camel.management.event.RouteStartedEvent;
-import org.apache.camel.management.event.RouteStoppedEvent;
+import org.apache.camel.processor.SendProcessor;
 import org.apache.camel.spi.EventNotifier;
 
 /**
  * @version $Revision$
  */
-public class EventNotifierEventsTest extends ContextTestSupport {
+public class EventNotifierFailreHandledEventsTest extends ContextTestSupport {
 
     private static List<EventObject> events = new ArrayList<EventObject>();
 
@@ -49,6 +47,11 @@
     }
 
     @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    @Override
     protected CamelContext createCamelContext() throws Exception {
         DefaultCamelContext context = new DefaultCamelContext(createRegistry());
         context.getManagementStrategy().setEventNotifier(new EventNotifier() {
@@ -63,66 +66,62 @@
         return context;
     }
 
-    public void testExchangeDone() throws Exception {
-        getMockEndpoint("mock:result").expectedMessageCount(1);
+    public void testExchangeDeadLetterChannel() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                errorHandler(deadLetterChannel("mock:dead"));
 
-        template.sendBody("direct:start", "Hello World");
+                from("direct:start").throwException(new IllegalArgumentException("Damn"));
+            }
+        });
+        context.start();
 
+        getMockEndpoint("mock:dead").expectedMessageCount(1);
+        template.sendBody("direct:start", "Hello World");
         assertMockEndpointsSatisfied();
 
         assertEquals(6, events.size());
         assertIsInstanceOf(CamelContextStartingEvent.class, events.get(0));
         assertIsInstanceOf(RouteStartedEvent.class, events.get(1));
-        assertIsInstanceOf(RouteStartedEvent.class, events.get(2));
-        assertIsInstanceOf(CamelContextStartedEvent.class, events.get(3));
-        assertIsInstanceOf(ExchangeCreatedEvent.class, events.get(4));
-        assertIsInstanceOf(ExchangeCompletedEvent.class, events.get(5));
+        assertIsInstanceOf(CamelContextStartedEvent.class, events.get(2));
+        assertIsInstanceOf(ExchangeCreatedEvent.class, events.get(3));
 
-        context.stop();
+        ExchangeFailureHandledEvent e = assertIsInstanceOf(ExchangeFailureHandledEvent.class, events.get(4));
+        assertEquals("should be DLC", true, e.isDeadLetterChannel());
+        SendProcessor send = assertIsInstanceOf(SendProcessor.class, e.getFailureHandler());
+        assertEquals("mock://dead", send.getDestination().getEndpointUri());
 
-        assertEquals(10, events.size());
-        assertIsInstanceOf(CamelContextStoppingEvent.class, events.get(6));
-        assertIsInstanceOf(RouteStoppedEvent.class, events.get(7));
-        assertIsInstanceOf(RouteStoppedEvent.class, events.get(8));
-        assertIsInstanceOf(CamelContextStoppedEvent.class, events.get(9));
+        // dead letter channel will mark the exchange as completed
+        assertIsInstanceOf(ExchangeCompletedEvent.class, events.get(5));
     }
 
-    public void testExchangeFailed() throws Exception {
-        try {
-            template.sendBody("direct:fail", "Hello World");
-            fail("Should have thrown an exception");
-        } catch (Exception e) {
-            // expected
-            assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
-        }
+    public void testExchangeOnException() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                onException(IllegalArgumentException.class).handled(true).to("mock:dead");
+
+                from("direct:start").throwException(new IllegalArgumentException("Damn"));
+            }
+        });
+        context.start();
+
+        getMockEndpoint("mock:dead").expectedMessageCount(1);
+        template.sendBody("direct:start", "Hello World");
+        assertMockEndpointsSatisfied();
 
         assertEquals(6, events.size());
         assertIsInstanceOf(CamelContextStartingEvent.class, events.get(0));
         assertIsInstanceOf(RouteStartedEvent.class, events.get(1));
-        assertIsInstanceOf(RouteStartedEvent.class, events.get(2));
-        assertIsInstanceOf(CamelContextStartedEvent.class, events.get(3));
-        assertIsInstanceOf(ExchangeCreatedEvent.class, events.get(4));
-        assertIsInstanceOf(ExchangeFailedEvent.class, events.get(5));
-
-        context.stop();
-
-        assertEquals(10, events.size());
-        assertIsInstanceOf(CamelContextStoppingEvent.class, events.get(6));
-        assertIsInstanceOf(RouteStoppedEvent.class, events.get(7));
-        assertIsInstanceOf(RouteStoppedEvent.class, events.get(8));
-        assertIsInstanceOf(CamelContextStoppedEvent.class, events.get(9));
-    }
+        assertIsInstanceOf(CamelContextStartedEvent.class, events.get(2));
+        assertIsInstanceOf(ExchangeCreatedEvent.class, events.get(3));
 
-    @Override
-    protected RouteBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                from("direct:start").to("log:foo").to("mock:result");
+        ExchangeFailureHandledEvent e = assertIsInstanceOf(ExchangeFailureHandledEvent.class, events.get(4));
+        assertEquals("should NOT be DLC", false, e.isDeadLetterChannel());
 
-                from("direct:fail").throwException(new IllegalArgumentException("Damn"));
-            }
-        };
+        // dead letter channel will mark the exchange as completed
+        assertIsInstanceOf(ExchangeCompletedEvent.class, events.get(5));
     }
 
-}
+}
\ No newline at end of file