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/04/19 16:15:51 UTC

svn commit: r766471 - in /camel/trunk: camel-core/src/main/java/org/apache/camel/model/ camel-core/src/main/java/org/apache/camel/processor/ camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/ camel-core/src/main/java/org/apache/camel/...

Author: davsclaus
Date: Sun Apr 19 14:15:49 2009
New Revision: 766471

URL: http://svn.apache.org/viewvc?rev=766471&view=rev
Log:
CAMEL-1540: Improved TryProcessor so its more like exception clause.

Added:
    camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorHandleWrappedExceptionTest.java
      - copied, changed from r766384, camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorHandleTest.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorMultipleExceptionTest.java   (with props)
    camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorOnWhenTest.java   (with props)
    camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringTryProcessorOnWhenTest.java
      - copied, changed from r766384, camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringWireTapTest.java
    camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/SpringTryProcessorOnWhenTest.xml
      - copied, changed from r766384, camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/SpringWireTapTest.xml
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/CatchDefinition.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/OnExceptionDefinition.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/TryDefinition.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/CatchProcessor.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/TryProcessor.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/util/ProcessorDefinitionHelper.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorHandleTest.java

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/CatchDefinition.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/CatchDefinition.java?rev=766471&r1=766470&r2=766471&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/CatchDefinition.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/CatchDefinition.java Sun Apr 19 14:15:49 2009
@@ -26,7 +26,9 @@
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlTransient;
 
+import org.apache.camel.Predicate;
 import org.apache.camel.Processor;
+import org.apache.camel.builder.ExpressionClause;
 import org.apache.camel.processor.CatchProcessor;
 import org.apache.camel.spi.RouteContext;
 import org.apache.camel.util.ObjectHelper;
@@ -41,6 +43,8 @@
 public class CatchDefinition extends ProcessorDefinition<CatchDefinition> {
     @XmlElement(name = "exception")
     private List<String> exceptions = new ArrayList<String>();
+    @XmlElement(name = "onWhen", required = false)
+    private WhenDefinition onWhen;
     @XmlElementRef
     private List<ProcessorDefinition> outputs = new ArrayList<ProcessorDefinition>();
     @XmlTransient
@@ -76,7 +80,13 @@
     @Override
     public CatchProcessor createProcessor(RouteContext routeContext) throws Exception {
         Processor childProcessor = routeContext.createProcessor(this);
-        return new CatchProcessor(getExceptionClasses(), childProcessor);
+
+        Predicate when = null;
+        if (onWhen != null) {
+            when = onWhen.getExpression().createPredicate(routeContext);
+        }
+
+        return new CatchProcessor(getExceptionClasses(), childProcessor, when);
     }
 
     public List<ProcessorDefinition> getOutputs() {
@@ -112,6 +122,36 @@
     }
     
     /**
+     * Sets an additional predicate that should be true before the onCatch is triggered.
+     * <p/>
+     * To be used for fine grained controlling whether a thrown exception should be intercepted
+     * by this exception type or not.
+     *
+     * @param predicate  predicate that determines true or false
+     * @return the builder
+     */
+    public CatchDefinition onWhen(Predicate predicate) {
+        setOnWhen(new WhenDefinition(predicate));
+        return this;
+    }
+
+    /**
+     * Creates an expression to configure an additional predicate that should be true before the
+     * onCatch is triggered.
+     * <p/>
+     * To be used for fine grained controlling whether a thrown exception should be intercepted
+     * by this exception type or not.
+     *
+     * @return the expression clause to configure
+     */
+    public ExpressionClause<CatchDefinition> onWhen() {
+        onWhen = new WhenDefinition();
+        ExpressionClause<CatchDefinition> clause = new ExpressionClause<CatchDefinition>(this);
+        onWhen.setExpression(clause);
+        return clause;
+    }
+
+    /**
      * Sets the exception class that the CatchType want to catch
      *
      * @param exception  the exception of class
@@ -131,6 +171,14 @@
         this.exceptions = exceptions;
     }
 
+    public WhenDefinition getOnWhen() {
+        return onWhen;
+    }
+
+    public void setOnWhen(WhenDefinition onWhen) {
+        this.onWhen = onWhen;
+    }
+
     protected List<Class> createExceptionClasses() {
         List<String> list = getExceptions();
         List<Class> answer = new ArrayList<Class>(list.size());

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/OnExceptionDefinition.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/OnExceptionDefinition.java?rev=766471&r1=766470&r2=766471&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/OnExceptionDefinition.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/OnExceptionDefinition.java Sun Apr 19 14:15:49 2009
@@ -136,7 +136,7 @@
     @Override
     public CatchProcessor createProcessor(RouteContext routeContext) throws Exception {
         Processor childProcessor = routeContext.createProcessor(this);
-        return new CatchProcessor(getExceptionClasses(), childProcessor);
+        return new CatchProcessor(getExceptionClasses(), childProcessor, null);
     }
 
 

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/TryDefinition.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/TryDefinition.java?rev=766471&r1=766470&r2=766471&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/TryDefinition.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/TryDefinition.java Sun Apr 19 14:15:49 2009
@@ -17,6 +17,8 @@
 package org.apache.camel.model;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
 import java.util.List;
 
 import javax.xml.bind.annotation.XmlAccessType;
@@ -24,10 +26,13 @@
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlTransient;
 
+import org.apache.camel.Predicate;
 import org.apache.camel.Processor;
+import org.apache.camel.builder.ExpressionClause;
 import org.apache.camel.processor.CatchProcessor;
 import org.apache.camel.processor.TryProcessor;
 import org.apache.camel.spi.RouteContext;
+import org.apache.camel.util.ProcessorDefinitionHelper;
 
 /**
  * Represents an XML &lt;try/&gt; element
@@ -64,12 +69,14 @@
         if (finallyClause != null) {
             finallyProcessor = finallyClause.createProcessor(routeContext);
         }
+
         List<CatchProcessor> catchProcessors = new ArrayList<CatchProcessor>();
         if (catchClauses != null) {
             for (CatchDefinition catchClause : catchClauses) {
                 catchProcessors.add(catchClause.createProcessor(routeContext));
             }
         }
+
         return new TryProcessor(tryProcessor, catchProcessors, finallyProcessor);
     }
 
@@ -77,20 +84,63 @@
     // -------------------------------------------------------------------------
 
     /**
-     * Handles the given exception
+     * Handles the given exception(s)
      *
-     * @param exceptionType  the exception
+     * @param exceptionType  the exception(s)
      * @return the try builder
      */
-    public TryDefinition doCatch(Class<?> exceptionType) {
+    public TryDefinition doCatch(Class... exceptionType) {
         popBlock();
-        CatchDefinition answer = new CatchDefinition(exceptionType);
+        List<Class> list = Arrays.asList(exceptionType);
+        CatchDefinition answer = new CatchDefinition(list);
         addOutput(answer);
         pushBlock(answer);
         return this;
     }
 
     /**
+     * Sets an additional predicate that should be true before the onCatch is triggered.
+     * <p/>
+     * To be used for fine grained controlling whether a thrown exception should be intercepted
+     * by this exception type or not.
+     *
+     * @param predicate  predicate that determines true or false
+     * @return the builder
+     */
+    public TryDefinition onWhen(Predicate predicate) {
+        // set the onWhen predicate on all the catch definitions
+        Iterator<CatchDefinition> it = ProcessorDefinitionHelper.filterTypeInOutputs(getOutputs(), CatchDefinition.class);
+        while (it.hasNext()) {
+            CatchDefinition doCatch = it.next();
+            doCatch.setOnWhen(new WhenDefinition(predicate));
+        }
+        return this;
+    }
+
+    /**
+     * Creates an expression to configure an additional predicate that should be true before the
+     * onCatch is triggered.
+     * <p/>
+     * To be used for fine grained controlling whether a thrown exception should be intercepted
+     * by this exception type or not.
+     *
+     * @return the expression clause to configure
+     */
+    public ExpressionClause<TryDefinition> onWhen() {
+        WhenDefinition answer = new WhenDefinition();
+        // set the onWhen definition on all the catch definitions
+        Iterator<CatchDefinition> it = ProcessorDefinitionHelper.filterTypeInOutputs(getOutputs(), CatchDefinition.class);
+        while (it.hasNext()) {
+            CatchDefinition doCatch = it.next();
+            doCatch.setOnWhen(answer);
+        }
+        // return a expression clause as builder to set the predicate on the onWhen definition
+        ExpressionClause<TryDefinition> clause = new ExpressionClause<TryDefinition>(this);
+        answer.setExpression(clause);
+        return clause;
+    }
+
+    /**
      * The finally block for a given handle
      *
      * @return  the try builder
@@ -170,4 +220,5 @@
             }
         }
     }
+
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/CatchProcessor.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/CatchProcessor.java?rev=766471&r1=766470&r2=766471&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/CatchProcessor.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/CatchProcessor.java Sun Apr 19 14:15:49 2009
@@ -16,9 +16,13 @@
  */
 package org.apache.camel.processor;
 
+import java.util.Iterator;
 import java.util.List;
 
+import org.apache.camel.Exchange;
+import org.apache.camel.Predicate;
 import org.apache.camel.Processor;
+import org.apache.camel.util.ObjectHelper;
 
 /**
  * A processor which catches exceptions.
@@ -27,10 +31,12 @@
  */
 public class CatchProcessor extends DelegateProcessor {
     private final List<Class> exceptions;
+    private final Predicate onWhen;
 
-    public CatchProcessor(List<Class> exceptions, Processor processor) {
+    public CatchProcessor(List<Class> exceptions, Processor processor, Predicate onWhen) {
         super(processor);
         this.exceptions = exceptions;
+        this.onWhen = onWhen;
     }
 
     @Override
@@ -38,16 +44,45 @@
         return "Catch[" + exceptions + " -> " + getProcessor() + "]";
     }
 
-    public boolean catches(Throwable e) {
-        for (Class type : exceptions) {
-            if (type.isInstance(e)) {
-                return true;
+    public boolean catches(Exchange exchange, Throwable exception) {
+        // use the exception iterator to walk the caused by hierachy
+        Iterator<Throwable> it = ObjectHelper.createExceptionIterator(exception);
+        while (it.hasNext()) {
+            Throwable e = it.next();
+            // see if we catch this type
+            for (Class type : exceptions) {
+                if (type.isInstance(e) && matchesWhen(exchange)) {
+                    return true;
+                }
             }
         }
+
+        // not found
         return false;
     }
 
     public List<Class> getExceptions() {
         return exceptions;
     }
+
+    /**
+     * Strategy method for matching the exception type with the current exchange.
+     * <p/>
+     * This default implementation will match as:
+     * <ul>
+     * <li>Always true if no when predicate on the exception type
+     * <li>Otherwise the when predicate is matches against the current exchange
+     * </ul>
+     *
+     * @param exchange the current {@link org.apache.camel.Exchange}
+     * @return <tt>true</tt> if matched, <tt>false</tt> otherwise.
+     */
+    protected boolean matchesWhen(Exchange exchange) {
+        if (onWhen == null) {
+            // if no predicate then it's always a match
+            return true;
+        }
+        return onWhen.matches(exchange);
+    }
+
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/TryProcessor.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/TryProcessor.java?rev=766471&r1=766470&r2=766471&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/TryProcessor.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/TryProcessor.java Sun Apr 19 14:15:49 2009
@@ -69,9 +69,6 @@
         // handle any exception occured during the try processor
         try {
             if (e != null) {
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("Caught exception while processing exchange.", e);
-                }
                 handleException(exchange, e);
             }
         } finally {
@@ -91,7 +88,11 @@
 
     protected void handleException(Exchange exchange, Throwable e) throws Exception {
         for (CatchProcessor catchClause : catchClauses) {
-            if (catchClause.catches(e)) {
+            if (catchClause.catches(exchange, e)) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("This TryProcessor handles the exception: " + e.getClass().getName() + " caused by: " + e.getMessage());
+                }
+
                 // lets attach the exception to the exchange
                 Exchange localExchange = exchange.copy();
                 
@@ -106,6 +107,9 @@
                 return;
             }
         }
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("This TryProcessor does not handle the exception: " + e.getClass().getName() + " caused by: " + e.getMessage());
+        }
     }
 
     protected void processFinally(Exchange exchange) throws Exception {

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java?rev=766471&r1=766470&r2=766471&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/exceptionpolicy/DefaultExceptionPolicyStrategy.java Sun Apr 19 14:15:49 2009
@@ -151,16 +151,16 @@
      * <li>Otherwise the when predicate is matches against the current exchange
      * </ul>
      *
-     * @param type     the exception type
+     * @param definition     the exception definition
      * @param exchange the current {@link Exchange}
      * @return <tt>true</tt> if matched, <tt>false</tt> otherwise.
      */
-    protected boolean matchesWhen(OnExceptionDefinition type, Exchange exchange) {
-        if (type.getOnWhen() == null || type.getOnWhen().getExpression() == null) {
+    protected boolean matchesWhen(OnExceptionDefinition definition, Exchange exchange) {
+        if (definition.getOnWhen() == null || definition.getOnWhen().getExpression() == null) {
             // if no predicate then it's always a match
             return true;
         }
-        return type.getOnWhen().getExpression().matches(exchange);
+        return definition.getOnWhen().getExpression().matches(exchange);
     }
 
     /**

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/ProcessorDefinitionHelper.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ProcessorDefinitionHelper.java?rev=766471&r1=766470&r2=766471&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/util/ProcessorDefinitionHelper.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/ProcessorDefinitionHelper.java Sun Apr 19 14:15:49 2009
@@ -16,6 +16,8 @@
  */
 package org.apache.camel.util;
 
+import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
 import org.apache.camel.model.ChoiceDefinition;
@@ -33,31 +35,50 @@
 
     /**
      * Looks for the given type in the list of outputs and recurring all the children as well.
+     *
+     * @param outputs  list of outputs, can be null or empty.
+     * @param type     the type to look for
+     * @return         the found definitions, or <tt>null</tt> if not found
+     */
+    public static <T> Iterator<T> filterTypeInOutputs(List<ProcessorDefinition> outputs, Class<T> type) {
+        List<T> found = new ArrayList<T>();
+        doFindType(outputs, type, found);
+        return found.iterator();
+    }
+
+    /**
+     * Looks for the given type in the list of outputs and recurring all the children as well.
      * Will stop at first found and return it.
      *
      * @param outputs  list of outputs, can be null or empty.
      * @param type     the type to look for
      * @return         the first found type, or <tt>null</tt> if not found
      */
-    @SuppressWarnings("unchecked")
     public static <T> T findFirstTypeInOutputs(List<ProcessorDefinition> outputs, Class<T> type) {
-        if (outputs == null || outputs.isEmpty()) {
+        List<T> found = new ArrayList<T>();
+        doFindType(outputs, type, found);
+        if (found.isEmpty()) {
             return null;
         }
+        return found.iterator().next();
+    }
+
+    @SuppressWarnings("unchecked")
+    private static void doFindType(List<ProcessorDefinition> outputs, Class<?> type, List found) {
+        if (outputs == null || outputs.isEmpty()) {
+            return;
+        }
 
         for (ProcessorDefinition out : outputs) {
             if (type.isInstance(out)) {
-                return type.cast(out);
+                found.add(out);
             }
 
             // send is much common
             if (out instanceof SendDefinition) {
                 SendDefinition send = (SendDefinition) out;
                 List<ProcessorDefinition> children = send.getOutputs();
-                T child = findFirstTypeInOutputs(children, type);
-                if (child != null) {
-                    return child;
-                }
+                doFindType(children, type, found);
             }
 
             // special for choice
@@ -65,31 +86,20 @@
                 ChoiceDefinition choice = (ChoiceDefinition) out;
                 for (WhenDefinition when : choice.getWhenClauses()) {
                     List<ProcessorDefinition> children = when.getOutputs();
-                    T child = findFirstTypeInOutputs(children, type);
-                    if (child != null) {
-                        return child;
-                    }
+                    doFindType(children, type, found);
                 }
 
                 // otherwise is optional
                 if (choice.getOtherwise() != null) {
                     List<ProcessorDefinition> children = choice.getOtherwise().getOutputs();
-                    T child = findFirstTypeInOutputs(children, type);
-                    if (child != null) {
-                        return child;
-                    }
+                    doFindType(children, type, found);
                 }
             }
 
             // try children as well
             List<ProcessorDefinition> children = out.getOutputs();
-            T child = findFirstTypeInOutputs(children, type);
-            if (child != null) {
-                return child;
-            }
+            doFindType(children, type, found);
         }
-
-        return null;
     }
 
 }

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorHandleTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorHandleTest.java?rev=766471&r1=766470&r2=766471&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorHandleTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorHandleTest.java Sun Apr 19 14:15:49 2009
@@ -49,7 +49,7 @@
                         .process(new ProcessorFail())
                         .to("mock:result")
                     .doCatch(Exception.class)
-                      .process(new ProcessorHandle())
+                        .process(new ProcessorHandle())
                     .doFinally()
                         .to("mock:finally")
                     .end();

Copied: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorHandleWrappedExceptionTest.java (from r766384, camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorHandleTest.java)
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorHandleWrappedExceptionTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorHandleWrappedExceptionTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorHandleTest.java&r1=766384&r2=766471&rev=766471&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorHandleTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorHandleWrappedExceptionTest.java Sun Apr 19 14:15:49 2009
@@ -23,9 +23,9 @@
 import org.apache.camel.component.mock.MockEndpoint;
 
 /**
- * Unit test for try .. handle routing (CAMEL-564).
+ * Unit test for try .. handle routing where it should handle wrapped exceptions as well.
  */
-public class TryProcessorHandleTest extends ContextTestSupport {
+public class TryProcessorHandleWrappedExceptionTest extends ContextTestSupport {
 
     private boolean handled;
 
@@ -48,8 +48,8 @@
                     .doTry()
                         .process(new ProcessorFail())
                         .to("mock:result")
-                    .doCatch(Exception.class)
-                      .process(new ProcessorHandle())
+                    .doCatch(IllegalStateException.class)
+                         .process(new ProcessorHandle())
                     .doFinally()
                         .to("mock:finally")
                     .end();
@@ -76,4 +76,4 @@
         }
     }
 
-}
+}
\ No newline at end of file

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorMultipleExceptionTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorMultipleExceptionTest.java?rev=766471&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorMultipleExceptionTest.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorMultipleExceptionTest.java Sun Apr 19 14:15:49 2009
@@ -0,0 +1,88 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.processor;
+
+import java.io.IOException;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+
+/**
+ * Unit test for try .. handle with multiple exceptions.
+ */
+public class TryProcessorMultipleExceptionTest extends ContextTestSupport {
+
+    public void testIOException() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(0);
+        getMockEndpoint("mock:catch").expectedMessageCount(1);
+        getMockEndpoint("mock:finally").expectedMessageCount(1);
+
+        sendBody("direct:start", "Damn IO");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    public void testIllegalStateException() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(0);
+        getMockEndpoint("mock:catch").expectedMessageCount(1);
+        getMockEndpoint("mock:finally").expectedMessageCount(1);
+
+        sendBody("direct:start", "Damn State");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    public void testOk() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+        getMockEndpoint("mock:catch").expectedMessageCount(0);
+        getMockEndpoint("mock:finally").expectedMessageCount(1);
+
+        sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:start")
+                    .doTry()
+                        .process(new ProcessorFail())
+                        .to("mock:result")
+                    .doCatch(IOException.class, IllegalStateException.class)
+                        .to("mock:catch")
+                    .doFinally()
+                        .to("mock:finally")
+                    .end();
+            }
+        };
+    }
+
+    private class ProcessorFail implements Processor {
+        public void process(Exchange exchange) throws Exception {
+            String body = exchange.getIn().getBody(String.class);
+            if ("Damn IO".equals(body)) {
+                throw new IOException("Damn IO");
+            } else if ("Damn State".equals(body)) {
+                throw new IllegalStateException("Damn State");
+            }
+        }
+    }
+
+}
\ No newline at end of file

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorMultipleExceptionTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorMultipleExceptionTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorOnWhenTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorOnWhenTest.java?rev=766471&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorOnWhenTest.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorOnWhenTest.java Sun Apr 19 14:15:49 2009
@@ -0,0 +1,137 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.processor;
+
+import java.io.IOException;
+
+import org.apache.camel.CamelExchangeException;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.builder.RouteBuilder;
+
+/**
+ * Unit test for try .. handle with onWhen.
+ */
+public class TryProcessorOnWhenTest extends ContextTestSupport {
+
+    public void testIOException() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(0);
+        getMockEndpoint("mock:catch").expectedMessageCount(1);
+        getMockEndpoint("mock:catchCamel").expectedMessageCount(0);
+        getMockEndpoint("mock:finally").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Damn IO");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    public void testIllegalStateException() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(0);
+        getMockEndpoint("mock:catch").expectedMessageCount(1);
+        getMockEndpoint("mock:catchCamel").expectedMessageCount(0);
+        getMockEndpoint("mock:finally").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Damn State");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    public void testCamelException() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(0);
+        getMockEndpoint("mock:catch").expectedMessageCount(0);
+        getMockEndpoint("mock:catchCamel").expectedMessageCount(1);
+        getMockEndpoint("mock:finally").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Camel");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    public void testOtherBug() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(0);
+        getMockEndpoint("mock:catch").expectedMessageCount(0);
+        getMockEndpoint("mock:catchCamel").expectedMessageCount(0);
+        getMockEndpoint("mock:finally").expectedMessageCount(1);
+
+        try {
+            template.sendBody("direct:start", "Other Bug");
+            fail("Should have thrown a RuntimeCamelException");
+        } catch (RuntimeCamelException e) {
+            assertIsInstanceOf(IllegalStateException.class, e.getCause());
+            assertEquals("Other Bug", e.getCause().getMessage());
+        }
+
+        assertMockEndpointsSatisfied();
+    }
+
+    public void testOk() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+        getMockEndpoint("mock:catch").expectedMessageCount(0);
+        getMockEndpoint("mock:finally").expectedMessageCount(1);
+
+        sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                // START SNIPPET: e1
+                from("direct:start")
+                    // here is our try where we try processing the exchange in the route below if it fails
+                    // we can catch it below, just like regular try .. catch .. finally in Java
+                    .doTry()
+                        .process(new ProcessorFail())
+                        .to("mock:result")
+                    // here we catch the following 2 exceptions but only if
+                    // the onWhen predicate matches, eg if the exception messsage
+                    // conatins the string word Damn
+                    .doCatch(IOException.class, IllegalStateException.class)
+                        .onWhen(exceptionMessage().contains("Damn"))
+                        .to("mock:catch")
+                    // another catch for CamelExchangeException that does not have any onWhen predicate
+                    .doCatch(CamelExchangeException.class)
+                        .to("mock:catchCamel")
+                    // and the finally that is always processed
+                    .doFinally()
+                        .to("mock:finally")
+                    // here the try block ends
+                    .end();
+                // END SNIPPET: e1
+            }
+        };
+    }
+
+    public static class ProcessorFail implements Processor {
+        public void process(Exchange exchange) throws Exception {
+            String body = exchange.getIn().getBody(String.class);
+            if ("Damn IO".equals(body)) {
+                throw new IOException("Damn IO");
+            } else if ("Damn State".equals(body)) {
+                throw new IllegalStateException("Damn State");
+            } else if ("Other Bug".equals(body)) {
+                throw new IllegalStateException("Other Bug");
+            } else if ("Camel".equals(body)) {
+                throw new CamelExchangeException("Sorry old Camel", exchange);
+            }
+        }
+    }
+
+}
\ No newline at end of file

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorOnWhenTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/TryProcessorOnWhenTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Copied: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringTryProcessorOnWhenTest.java (from r766384, camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringWireTapTest.java)
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringTryProcessorOnWhenTest.java?p2=camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringTryProcessorOnWhenTest.java&p1=camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringWireTapTest.java&r1=766384&r2=766471&rev=766471&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringWireTapTest.java (original)
+++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/processor/SpringTryProcessorOnWhenTest.java Sun Apr 19 14:15:49 2009
@@ -17,13 +17,13 @@
 package org.apache.camel.spring.processor;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.processor.WireTapTest;
+import org.apache.camel.processor.TryProcessorOnWhenTest;
 import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
 
-public class SpringWireTapTest extends WireTapTest {
+public class SpringTryProcessorOnWhenTest extends TryProcessorOnWhenTest {
 
     protected CamelContext createCamelContext() throws Exception {
-        return createSpringCamelContext(this, "org/apache/camel/spring/processor/SpringWireTapTest.xml");
+        return createSpringCamelContext(this, "org/apache/camel/spring/processor/SpringTryProcessorOnWhenTest.xml");
     }
 
 }
\ No newline at end of file

Copied: camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/SpringTryProcessorOnWhenTest.xml (from r766384, camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/SpringWireTapTest.xml)
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/SpringTryProcessorOnWhenTest.xml?p2=camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/SpringTryProcessorOnWhenTest.xml&p1=camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/SpringWireTapTest.xml&r1=766384&r2=766471&rev=766471&view=diff
==============================================================================
--- camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/SpringWireTapTest.xml (original)
+++ camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/SpringTryProcessorOnWhenTest.xml Sun Apr 19 14:15:49 2009
@@ -22,24 +22,38 @@
        http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
     ">
 
-
     <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
         <!-- START SNIPPET: e1 -->
         <route>
             <from uri="direct:start"/>
-            <to uri="log:foo"/>
-            <wireTap uri="direct:tap"/>
-            <to uri="mock:result"/>
+            <!-- here the try starts. its a try .. catch .. finally just as regular java code -->
+            <doTry>
+                <process ref="processorFail"/>
+                <to uri="mock:result"/>
+                <!-- here we catch the below 2 kind of exceptions but ONLY if the onWhen predicate matches
+                     that means that the exception message should contain the string word 'Damn' -->
+                <doCatch>
+                    <exception>java.io.IOException</exception>
+                    <exception>java.lang.IllegalStateException</exception>
+                    <onWhen>
+                        <simple>${exception.message} contains 'Damn'</simple>
+                    </onWhen>
+                    <to uri="mock:catch"/>
+                </doCatch>
+                <!-- we can have multiple catch blocks for different exception and with their own onWhen -->
+                <doCatch>
+                    <exception>org.apache.camel.CamelExchangeException</exception>
+                    <to uri="mock:catchCamel"/>
+                </doCatch>
+                <!-- the finally is always processed -->
+                <doFinally>
+                    <to uri="mock:finally"/>
+                </doFinally>
+            </doTry>
         </route>
         <!-- END SNIPPET: e1 -->
-
-        <route>
-            <from uri="direct:tap"/>
-            <delay delayTime="1000"><constant/></delay>
-            <setBody><constant>Tapped</constant></setBody>
-            <to uri="mock:result"/>
-            <to uri="mock:tap"/>
-        </route>
     </camelContext>
 
+    <bean id="processorFail" class="org.apache.camel.processor.TryProcessorOnWhenTest$ProcessorFail"/>
+
 </beans>