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/06/26 13:46:18 UTC

svn commit: r788663 - in /camel/trunk/camel-core/src: main/java/org/apache/camel/impl/ main/java/org/apache/camel/model/ main/java/org/apache/camel/processor/ main/java/org/apache/camel/processor/interceptor/ main/java/org/apache/camel/spi/ test/java/o...

Author: davsclaus
Date: Fri Jun 26 11:46:17 2009
New Revision: 788663

URL: http://svn.apache.org/viewvc?rev=788663&view=rev
Log:
CAMEL-1759: Introduced RouteNode to represent a node in the route path. Currently used by tracer. In future also used by Channel. Tracer now more fine grained to trace intercept/onException etc.

Added:
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultRouteNode.java   (with props)
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteNode.java   (with props)
    camel/trunk/camel-core/src/test/java/org/apache/camel/processor/intercept/DualInterceptSimpleRouteTest.java
      - copied, changed from r788579, camel/trunk/camel-core/src/test/java/org/apache/camel/processor/intercept/InterceptSimpleRouteTest.java
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultUnitOfWork.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/InterceptDefinition.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/RoutesDefinition.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/Traceable.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/interceptor/DefaultTraceEventMessage.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/interceptor/DefaultTraceFormatter.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/interceptor/TraceInterceptor.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/spi/TraceableUnitOfWork.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/issues/MultipleFromTest.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TraceableUnitOfWorkTest.java

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultRouteNode.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultRouteNode.java?rev=788663&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultRouteNode.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultRouteNode.java Fri Jun 26 11:46:17 2009
@@ -0,0 +1,51 @@
+/**
+ * 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.impl;
+
+import org.apache.camel.Processor;
+import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.RouteNode;
+
+/**
+ * A default implementation of the {@link org.apache.camel.model.RouteNode}
+ *
+ * @version $Revision$
+ */
+public class DefaultRouteNode implements RouteNode {
+
+    private Processor processor;
+    private ProcessorDefinition processorDefinition;
+
+    public DefaultRouteNode(Processor processor, ProcessorDefinition processorDefinition) {
+        this.processor = processor;
+        this.processorDefinition = processorDefinition;
+    }
+
+    public Processor getProcessor() {
+        return processor;
+    }
+
+    public ProcessorDefinition getProcessorDefinition() {
+        return processorDefinition;
+    }
+
+    @Override
+    public String toString() {
+        return "RouteNode[" + processorDefinition + "]";
+    }
+
+}

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultRouteNode.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultRouteNode.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultUnitOfWork.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultUnitOfWork.java?rev=788663&r1=788662&r2=788663&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultUnitOfWork.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultUnitOfWork.java Fri Jun 26 11:46:17 2009
@@ -18,11 +18,15 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.camel.Exchange;
-import org.apache.camel.Processor;
 import org.apache.camel.Service;
+import org.apache.camel.model.InterceptDefinition;
+import org.apache.camel.model.RouteNode;
 import org.apache.camel.spi.Synchronization;
 import org.apache.camel.spi.TraceableUnitOfWork;
 import org.apache.camel.util.UuidGenerator;
@@ -40,7 +44,8 @@
 
     private String id;
     private List<Synchronization> synchronizations;
-    private List<Processor> processorList;
+    private List<RouteNode> routeNodes;
+    private Map<InterceptDefinition, AtomicInteger> interceptIndex = new HashMap<InterceptDefinition, AtomicInteger>();
     private Object originalInBody;
 
     public DefaultUnitOfWork(Exchange exchange) {
@@ -55,12 +60,11 @@
         // need to clean up when we are stopping to not leak memory
         if (synchronizations != null) {
             synchronizations.clear();
-            synchronizations = null;
         }
-        if (processorList != null) {
-            processorList.clear();
-            processorList = null;
+        if (routeNodes != null) {
+            routeNodes.clear();
         }
+        interceptIndex.clear();
         originalInBody = null;
     }
 
@@ -115,32 +119,42 @@
         return id;
     }
 
-    public void addInterceptedProcessor(Processor processor) {
-        if (processorList == null) {
-            processorList = new ArrayList<Processor>();
+    public void addTraced(RouteNode entry) {
+        if (routeNodes == null) {
+            routeNodes = new ArrayList<RouteNode>();
         }
-        processorList.add(processor);
+        routeNodes.add(entry);
     }
 
-    public Processor getLastInterceptedProcessor() {
-        if (processorList == null || processorList.isEmpty()) {
+    public RouteNode getLastNode() {
+        if (routeNodes == null || routeNodes.isEmpty()) {
             return null;
         }
-        return processorList.get(processorList.size() - 1);
+        return routeNodes.get(routeNodes.size() - 1);
     }
 
-    public Processor getSecondLastInterceptedProcessor() {
-        if (processorList == null || processorList.isEmpty() || processorList.size() == 1) {
+    public RouteNode getSecondLastNode() {
+        if (routeNodes == null || routeNodes.isEmpty() || routeNodes.size() == 1) {
             return null;
         }
-        return processorList.get(processorList.size() - 2);
+        return routeNodes.get(routeNodes.size() - 2);
     }
 
-    public List<Processor> getInterceptedProcessors() {
-        return Collections.unmodifiableList(processorList);
+    public List<RouteNode> getNodes() {
+        return Collections.unmodifiableList(routeNodes);
     }
 
     public Object getOriginalInBody() {
         return originalInBody;
     }
+
+    public int getAndIncrement(InterceptDefinition node) {
+        AtomicInteger count = interceptIndex.get(node);
+        if (count == null) {
+            count = new AtomicInteger();
+            interceptIndex.put(node, count);
+        }
+        return count.getAndIncrement();
+    }
+
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/InterceptDefinition.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/InterceptDefinition.java?rev=788663&r1=788662&r2=788663&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/InterceptDefinition.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/InterceptDefinition.java Fri Jun 26 11:46:17 2009
@@ -43,6 +43,9 @@
     @XmlTransient
     protected Processor output;
 
+    @XmlTransient
+    protected final List<Processor> intercepted = new ArrayList<Processor>();
+
     public InterceptDefinition() {
     }
 
@@ -68,14 +71,20 @@
 
         // add the output as a intercept strategy to the route context so its invoked on each processing step
         routeContext.getInterceptStrategies().add(new InterceptStrategy() {
+            private Processor interceptedTarget;
+
             public Processor wrapProcessorInInterceptors(ProcessorDefinition processorDefinition, Processor target, Processor nextTarget) throws Exception {
                 // prefer next target over taget as next target is the real target
-                Processor processor = nextTarget != null ? nextTarget : target;
-                if (processor != null) {
+                interceptedTarget = nextTarget != null ? nextTarget : target;
+
+                // remember the target that was intercepted
+                intercepted.add(interceptedTarget);
+
+                if (interceptedTarget != null) {
                     // wrap in a pipeline so we continue routing to the next
                     List<Processor> list = new ArrayList<Processor>(2);
                     list.add(output);
-                    list.add(processor);
+                    list.add(interceptedTarget);
                     return new Pipeline(list);
                 } else {
                     return output;
@@ -84,7 +93,7 @@
 
             @Override
             public String toString() {
-                return "intercept[" + output + "]";
+                return "intercept[" +  (interceptedTarget != null ? interceptedTarget : output) + "]";
             }
         });
 
@@ -133,4 +142,13 @@
         }
     }
 
+    public Processor getInterceptedProcessor(int index) {
+        // avoid out of bounds
+        if (index <= intercepted.size() - 1) {
+            return intercepted.get(index);
+        } else {
+            return null;
+        }
+    }
+
 }
\ No newline at end of file

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteNode.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteNode.java?rev=788663&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteNode.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteNode.java Fri Jun 26 11:46:17 2009
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.model;
+
+import org.apache.camel.Processor;
+
+/**
+ * Represents a model of a node in the runtime route path.
+ *
+ * @version $Revision$
+ */
+public interface RouteNode {
+
+    /**
+     * Gets the actual processor this node represents.
+     *
+     * @return the processor, can be <tt>null</tt> in special cases such as an intercepted node
+     */
+    Processor getProcessor();
+
+    /**
+     * Gets the model definition that represents this node
+     *
+     * @return the definition, is newer <tt>null</tt>
+     */
+    ProcessorDefinition getProcessorDefinition();
+}

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteNode.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/main/java/org/apache/camel/model/RouteNode.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/RoutesDefinition.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/RoutesDefinition.java?rev=788663&r1=788662&r2=788663&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/RoutesDefinition.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/RoutesDefinition.java Fri Jun 26 11:46:17 2009
@@ -255,7 +255,7 @@
      */
     public InterceptDefinition intercept() {
         InterceptDefinition answer = new InterceptDefinition();
-        getIntercepts().add(answer);
+        getIntercepts().add(0, answer);
         return answer;
     }
 

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/Traceable.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/Traceable.java?rev=788663&r1=788662&r2=788663&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/Traceable.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/Traceable.java Fri Jun 26 11:46:17 2009
@@ -31,6 +31,6 @@
      *
      * @return  the label
      */
-    public String getTraceLabel();
+    String getTraceLabel();
 
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/interceptor/DefaultTraceEventMessage.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/interceptor/DefaultTraceEventMessage.java?rev=788663&r1=788662&r2=788663&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/interceptor/DefaultTraceEventMessage.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/interceptor/DefaultTraceEventMessage.java Fri Jun 26 11:46:17 2009
@@ -22,8 +22,9 @@
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.Processor;
-import org.apache.camel.processor.Traceable;
 import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.RouteNode;
+import org.apache.camel.processor.Traceable;
 import org.apache.camel.spi.TraceableUnitOfWork;
 import org.apache.camel.util.MessageHelper;
 
@@ -81,7 +82,8 @@
 
     // Implementation
     //---------------------------------------------------------------
-    private String extractTraceLabel(Processor processor) {
+    private String extractTraceLabel(RouteNode entry) {
+        Processor processor = entry.getProcessor();
         if (processor instanceof Traceable) {
             Traceable trace = (Traceable) processor;
             return trace.getTraceLabel();
@@ -96,7 +98,7 @@
     private String extractFromNode(Exchange exchange) {
         if (exchange.getUnitOfWork() instanceof TraceableUnitOfWork) {
             TraceableUnitOfWork tuow = (TraceableUnitOfWork) exchange.getUnitOfWork();
-            Processor last = tuow.getSecondLastInterceptedProcessor();
+            RouteNode last = tuow.getSecondLastNode();
             return last != null ? extractTraceLabel(last) : null;
         }
         return null;
@@ -105,7 +107,7 @@
     private String extractToNode(Exchange exchange) {
         if (exchange.getUnitOfWork() instanceof TraceableUnitOfWork) {
             TraceableUnitOfWork tuow = (TraceableUnitOfWork) exchange.getUnitOfWork();
-            Processor last = tuow.getLastInterceptedProcessor();
+            RouteNode last = tuow.getLastNode();
             return last != null ? extractTraceLabel(last) : null;
         }
         return null;

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/interceptor/DefaultTraceFormatter.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/interceptor/DefaultTraceFormatter.java?rev=788663&r1=788662&r2=788663&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/interceptor/DefaultTraceFormatter.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/interceptor/DefaultTraceFormatter.java Fri Jun 26 11:46:17 2009
@@ -19,8 +19,9 @@
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.Processor;
-import org.apache.camel.processor.Traceable;
 import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.RouteNode;
+import org.apache.camel.processor.Traceable;
 import org.apache.camel.spi.TraceableUnitOfWork;
 import org.apache.camel.spi.UnitOfWork;
 import org.apache.camel.util.MessageHelper;
@@ -236,7 +237,13 @@
         }
     }
 
-    protected String getNodeMessage(Processor processor) {
+    protected String getNodeMessage(RouteNode entry) {
+        Processor processor = entry.getProcessor();
+
+        if (processor == null) {
+            return "";
+        }
+
         String message;
         if (processor instanceof Traceable) {
             Traceable trace = (Traceable) processor;
@@ -284,16 +291,16 @@
         if (showNode && exchange.getUnitOfWork() instanceof TraceableUnitOfWork) {
             TraceableUnitOfWork tuow = (TraceableUnitOfWork) exchange.getUnitOfWork();
 
-            Processor fromProcessor = tuow.getSecondLastInterceptedProcessor();
-            if (fromProcessor != null) {
-                from = getNodeMessage(fromProcessor);
+            RouteNode traceFrom = tuow.getSecondLastNode();
+            if (traceFrom != null) {
+                from = getNodeMessage(traceFrom);
             } else if (exchange.getFromEndpoint() != null) {
                 from = "from(" + exchange.getFromEndpoint().getEndpointUri() + ")";
             }
 
-            Processor toProcessor = tuow.getLastInterceptedProcessor();
-            if (toProcessor != null) {
-                to = getNodeMessage(toProcessor);
+            RouteNode traceTo = tuow.getLastNode();
+            if (traceTo != null) {
+                to = getNodeMessage(traceTo);
             }
         }
 

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/interceptor/TraceInterceptor.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/interceptor/TraceInterceptor.java?rev=788663&r1=788662&r2=788663&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/interceptor/TraceInterceptor.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/interceptor/TraceInterceptor.java Fri Jun 26 11:46:17 2009
@@ -24,11 +24,12 @@
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
+import org.apache.camel.impl.DefaultRouteNode;
+import org.apache.camel.model.InterceptDefinition;
+import org.apache.camel.model.OnExceptionDefinition;
 import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.processor.DelegateProcessor;
 import org.apache.camel.processor.Logger;
-import org.apache.camel.processor.Pipeline;
-import org.apache.camel.processor.MulticastProcessor;
 import org.apache.camel.spi.ExchangeFormatter;
 import org.apache.camel.spi.InterceptStrategy;
 import org.apache.camel.spi.TraceableUnitOfWork;
@@ -106,11 +107,59 @@
                 // if traceable then register this as the previous node, now it has been logged
                 if (exchange.getUnitOfWork() instanceof TraceableUnitOfWork) {
                     TraceableUnitOfWork tuow = (TraceableUnitOfWork) exchange.getUnitOfWork();
-                    tuow.addInterceptedProcessor(super.getProcessor());
+
+                    // special for on exception so we can see it in the trace logs
+                    if (node instanceof OnExceptionDefinition) {
+                        Processor pseudo = new Processor() {
+                            public void process(Exchange exchange) throws Exception {
+                            }
+
+                            public String toString() {
+                                String name = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class).getClass().getSimpleName();
+                                return "onException[" + name + "]";
+                            }
+                        };
+                        tuow.addTraced(new DefaultRouteNode(pseudo, node));
+
+                        // log and trace the processor that was onException so we can see it
+                        logExchange(exchange);
+                        traceExchange(exchange);
+                    }
+
+                    // register the processor that was traced
+                    tuow.addTraced(new DefaultRouteNode(super.getProcessor(), node));
                 }
 
+                // TODO: just a little more to avoid logging the last intercepted step
+
+                // log and trace the processor
                 logExchange(exchange);
                 traceExchange(exchange);
+
+                // some nodes need extra work to trace it
+                if (exchange.getUnitOfWork() instanceof TraceableUnitOfWork) {
+                    TraceableUnitOfWork tuow = (TraceableUnitOfWork) exchange.getUnitOfWork();
+
+                    // special for intercept() as we would like to trace the processor that was intercepted
+                    // as well, otherwise we only see the intercepted route, but we need the both to be logged/traced
+                    if (node instanceof InterceptDefinition) {
+
+                        // get the intercepted processor from the definition
+                        // we need to use the UoW to have its own index of how far we got into the list
+                        // of intercepted processors the intercept definition holds as the intercept
+                        // definition is a single object that is shared by concurrent thread being routed
+                        // so each exchange has its own private counter
+                        InterceptDefinition intercept = (InterceptDefinition) node;
+                        Processor last = intercept.getInterceptedProcessor(tuow.getAndIncrement(intercept));
+                        if (last != null) {
+                            tuow.addTraced(new DefaultRouteNode(last, node));
+
+                            // log and trace the processor that was intercepted so we can see it
+                            logExchange(exchange);
+                            traceExchange(exchange);
+                        }
+                    }
+                }
             }
 
             // process the exchange

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/spi/TraceableUnitOfWork.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/spi/TraceableUnitOfWork.java?rev=788663&r1=788662&r2=788663&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/spi/TraceableUnitOfWork.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/spi/TraceableUnitOfWork.java Fri Jun 26 11:46:17 2009
@@ -18,7 +18,8 @@
 
 import java.util.List;
 
-import org.apache.camel.Processor;
+import org.apache.camel.model.InterceptDefinition;
+import org.apache.camel.model.RouteNode;
 
 /**
  * A Unit of work that is also traceable with the
@@ -30,26 +31,38 @@
 public interface TraceableUnitOfWork extends UnitOfWork {
 
     /**
-     * Adds the given processor that was intercepted
+     * Adds the entry that was intercepted
      *
-     * @param processor the processor
+     * @param entry the entry
      */
-    void addInterceptedProcessor(Processor processor);
+    void addTraced(RouteNode entry);
 
     /**
-     * Gets the last intercepted processor, is <tt>null</tt> if no last exists.
+     * Gets the last node, is <tt>null</tt> if no last exists.
      */
-    Processor getLastInterceptedProcessor();
+    RouteNode getLastNode();
 
     /**
-     * Gets the 2nd last intercepted processor, is <tt>null</tt> if no last exists.
+     * Gets the 2nd last node, is <tt>null</tt> if no last exists.
      */
-    Processor getSecondLastInterceptedProcessor();
+    RouteNode getSecondLastNode();
 
     /**
-     * Gets the current list of intercepted processors, representing the route path the
-     * current {@link org.apache.camel.Exchange} has taken.
+     * Gets the current list of nodes, representing the route path the
+     * current {@link org.apache.camel.Exchange} has currently taken.
      */
-    List<Processor> getInterceptedProcessors();
+    List<RouteNode> getNodes();
+
+    /**
+     * A private counter that increments, is used to as book keeping how far this
+     * exchange have been intercepted by the general intercept().
+     * <p/>
+     * We need this special book keeping to keep correct order when dealing
+     * with concurrent exchanges being routed in the same route path.
+     *
+     * @param node the intercept node
+     * @return the current count
+     */
+    int getAndIncrement(InterceptDefinition node);
 
 }

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/issues/MultipleFromTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/issues/MultipleFromTest.java?rev=788663&r1=788662&r2=788663&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/issues/MultipleFromTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/issues/MultipleFromTest.java Fri Jun 26 11:46:17 2009
@@ -40,7 +40,7 @@
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
             public void configure() throws Exception {
-                from("direct:start").from("seda:in").to("mock:result");
+                from("direct:start", "seda:in").to("mock:result");
             }
         };
     }

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TraceableUnitOfWorkTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TraceableUnitOfWorkTest.java?rev=788663&r1=788662&r2=788663&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TraceableUnitOfWorkTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TraceableUnitOfWorkTest.java Fri Jun 26 11:46:17 2009
@@ -23,7 +23,7 @@
 import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.impl.JndiRegistry;
-import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.RouteNode;
 import org.apache.camel.spi.TraceableUnitOfWork;
 
 /**
@@ -72,9 +72,9 @@
             TraceableUnitOfWork tuow = (TraceableUnitOfWork) exchange.getUnitOfWork();
 
             // get the list of intercepted nodes
-            List<Processor> list = tuow.getInterceptedProcessors();
-            // get the 2nd last as the last is me (MyErrorProcessor)
-            Processor last = list.get(list.size() - 2);
+            List<RouteNode> list = tuow.getNodes();
+            // get the 3rd last as its the bean
+            Processor last = list.get(list.size() - 3).getProcessor();
 
             // set error message
             exchange.getFault().setBody("Failed at: " + last.toString());

Copied: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/intercept/DualInterceptSimpleRouteTest.java (from r788579, camel/trunk/camel-core/src/test/java/org/apache/camel/processor/intercept/InterceptSimpleRouteTest.java)
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/intercept/DualInterceptSimpleRouteTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/processor/intercept/DualInterceptSimpleRouteTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/processor/intercept/InterceptSimpleRouteTest.java&r1=788579&r2=788663&rev=788663&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/intercept/InterceptSimpleRouteTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/intercept/DualInterceptSimpleRouteTest.java Fri Jun 26 11:46:17 2009
@@ -22,14 +22,16 @@
 /**
  * @version $Revision$
  */
-public class InterceptSimpleRouteTest extends ContextTestSupport {
+public class DualInterceptSimpleRouteTest extends ContextTestSupport {
 
-    public void testIntercept() throws Exception {
+    public void testDualIntercept() throws Exception {
         getMockEndpoint("mock:foo").expectedMessageCount(1);
         getMockEndpoint("mock:bar").expectedMessageCount(1);
         getMockEndpoint("mock:result").expectedMessageCount(1);
 
-        getMockEndpoint("mock:intercepted").expectedMessageCount(3);
+        getMockEndpoint("mock:intercepted").expectedMessageCount(6);
+        getMockEndpoint("mock:a").expectedMessageCount(3);
+        getMockEndpoint("mock:b").expectedMessageCount(3);
 
         template.sendBody("direct:start", "Hello World");
 
@@ -43,11 +45,15 @@
             public void configure() throws Exception {
                 context.setTracing(true);
 
+                // it should genereally be avoid to have dual interceptors as its a bit confusing
+                // but you can do it anyway
                 intercept().to("mock:intercepted");
 
+                intercept().to("mock:a").to("mock:b");
+
                 from("direct:start")
                     .to("mock:foo").to("mock:bar").to("mock:result");
             }
         };
     }
-}
+}
\ No newline at end of file