You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by js...@apache.org on 2007/08/13 16:19:31 UTC

svn commit: r565361 - in /activemq/camel/trunk/camel-core/src: main/java/org/apache/camel/model/ main/java/org/apache/camel/processor/ main/resources/org/apache/camel/model/ test/java/org/apache/camel/processor/

Author: jstrachan
Date: Mon Aug 13 07:19:30 2007
New Revision: 565361

URL: http://svn.apache.org/viewvc?view=rev&rev=565361
Log:
added test case and fix for CAMEL-97

Added:
    activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/RedeliveryPolicyType.java   (with props)
    activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RedeliveryPolicyPerExceptionTest.java
      - copied, changed from r565311, activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelTest.java
Modified:
    activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/ExceptionType.java
    activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RedeliveryPolicy.java
    activemq/camel/trunk/camel-core/src/main/resources/org/apache/camel/model/jaxb.index

Modified: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/ExceptionType.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/ExceptionType.java?view=diff&rev=565361&r1=565360&r2=565361
==============================================================================
--- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/ExceptionType.java (original)
+++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/ExceptionType.java Mon Aug 13 07:19:30 2007
@@ -44,13 +44,14 @@
     private List<InterceptorType> interceptors = new ArrayList<InterceptorType>();
     @XmlElement(name = "exception")
     private List<String> exceptions = new ArrayList<String>();
+    @XmlElement(name = "redeliveryPolicy", required = false)
+    private RedeliveryPolicyType redeliveryPolicy;
     @XmlElementRef
     private List<ProcessorType> outputs = new ArrayList<ProcessorType>();
     @XmlTransient
     private List<Class> exceptionClasses;
     @XmlTransient
     private Processor errorHandler;
-    private Integer retry;
 
     public ExceptionType() {
     }
@@ -71,12 +72,21 @@
 
     /**
      * Allows an exception handler to create a new redelivery policy for this exception type
-     * @param redeliveryPolicy the current redelivery policy
+     * @param parentPolicy the current redelivery policy
      * @return a newly created redelivery policy, or return the original policy if no customization is required
      * for this exception handler.
      */
-    public RedeliveryPolicy createRedeliveryPolicy(RedeliveryPolicy redeliveryPolicy) {
-        return redeliveryPolicy;
+    public RedeliveryPolicy createRedeliveryPolicy(RedeliveryPolicy parentPolicy) {
+        if (redeliveryPolicy != null) {
+            return redeliveryPolicy.createRedeliveryPolicy(parentPolicy);
+        }
+        else if (errorHandler != null) {
+            // lets create a new error handler that has no retries
+            RedeliveryPolicy answer = parentPolicy.copy();
+            answer.setMaximumRedeliveries(0);
+            return answer;
+        }
+        return parentPolicy;
     }
 
     public void addRoutes(RouteContext routeContext, Collection<Route> routes) throws Exception {
@@ -92,6 +102,47 @@
         return new CatchProcessor(getExceptionClasses(), childProcessor);
     }
 
+
+    // Fluent API
+    //-------------------------------------------------------------------------
+    public ExceptionType backOffMultiplier(double backOffMultiplier) {
+        getOrCreateRedeliveryPolicy().backOffMultiplier(backOffMultiplier);
+        return this;
+    }
+
+    public ExceptionType collisionAvoidanceFactor(double collisionAvoidanceFactor) {
+        getOrCreateRedeliveryPolicy().collisionAvoidanceFactor(collisionAvoidanceFactor);
+        return this;
+    }
+
+    public ExceptionType collisionAvoidancePercent(short collisionAvoidancePercent) {
+        getOrCreateRedeliveryPolicy().collisionAvoidancePercent(collisionAvoidancePercent);
+        return this;
+    }
+
+    public ExceptionType initialRedeliveryDelay(long initialRedeliveryDelay) {
+        getOrCreateRedeliveryPolicy().initialRedeliveryDelay(initialRedeliveryDelay);
+        return this;
+    }
+
+    public ExceptionType maximumRedeliveries(int maximumRedeliveries) {
+        getOrCreateRedeliveryPolicy().maximumRedeliveries(maximumRedeliveries);
+        return this;
+    }
+
+    public ExceptionType useCollisionAvoidance() {
+        getOrCreateRedeliveryPolicy().useCollisionAvoidance();
+        return this;
+    }
+
+    public ExceptionType useExponentialBackOff() {
+        getOrCreateRedeliveryPolicy().useExponentialBackOff();
+        return this;
+    }
+
+
+    // Properties
+    //-------------------------------------------------------------------------
     public List<InterceptorType> getInterceptors() {
         return interceptors;
     }
@@ -131,6 +182,23 @@
         return errorHandler;
     }
 
+    public RedeliveryPolicyType getRedeliveryPolicy() {
+        return redeliveryPolicy;
+    }
+
+    public void setRedeliveryPolicy(RedeliveryPolicyType redeliveryPolicy) {
+        this.redeliveryPolicy = redeliveryPolicy;
+    }
+
+    // Implementation methods
+    //-------------------------------------------------------------------------
+    protected RedeliveryPolicyType getOrCreateRedeliveryPolicy() {
+        if (redeliveryPolicy == null) {
+            redeliveryPolicy = new RedeliveryPolicyType();
+        }
+        return redeliveryPolicy;
+    }
+    
     protected List<Class> createExceptionClasses() {
         List<String> list = getExceptions();
         List<Class> answer = new ArrayList<Class>(list.size());

Added: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/RedeliveryPolicyType.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/RedeliveryPolicyType.java?view=auto&rev=565361
==============================================================================
--- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/RedeliveryPolicyType.java (added)
+++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/model/RedeliveryPolicyType.java Mon Aug 13 07:19:30 2007
@@ -0,0 +1,159 @@
+/**
+ *
+ * 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.RedeliveryPolicy;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @version $Revision: 1.1 $
+ */
+@XmlRootElement(name = "redeliveryPolicy")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class RedeliveryPolicyType {
+    private Integer maximumRedeliveries;
+    private Long initialRedeliveryDelay;
+    private Double backOffMultiplier;
+    private Boolean useExponentialBackOff;
+    private Double collisionAvoidanceFactor;
+    private Boolean useCollisionAvoidance;
+
+
+    public RedeliveryPolicy createRedeliveryPolicy(RedeliveryPolicy parentPolicy) {
+        RedeliveryPolicy answer =  parentPolicy.copy();
+
+        // copy across the properties - if they are set
+        if (maximumRedeliveries != null) {
+            answer.setMaximumRedeliveries(maximumRedeliveries);
+        }
+        if (initialRedeliveryDelay != null) {
+            answer.setInitialRedeliveryDelay(initialRedeliveryDelay);
+        }
+        if (backOffMultiplier != null) {
+            answer.setBackOffMultiplier(backOffMultiplier);
+        }
+        if (useExponentialBackOff != null) {
+            answer.setUseExponentialBackOff(useExponentialBackOff);
+        }
+        if (collisionAvoidanceFactor != null) {
+            answer.setCollisionAvoidanceFactor(collisionAvoidanceFactor);
+        }
+        if (useCollisionAvoidance != null) {
+            answer.setUseCollisionAvoidance(useCollisionAvoidance);
+        }
+        return answer;
+    }
+
+    public String toString() {
+        return "RedeliveryPolicy[maxRedeliveries: " + maximumRedeliveries + "]";
+    }
+
+    // Fluent API
+    //-------------------------------------------------------------------------
+    public RedeliveryPolicyType backOffMultiplier(double backOffMultiplier) {
+        setBackOffMultiplier(backOffMultiplier);
+        return this;
+    }
+
+    public RedeliveryPolicyType collisionAvoidancePercent(double collisionAvoidancePercent) {
+        setCollisionAvoidanceFactor(collisionAvoidancePercent * 0.01d);
+        return this;
+    }
+
+    public RedeliveryPolicyType collisionAvoidanceFactor(double collisionAvoidanceFactor) {
+        setCollisionAvoidanceFactor(collisionAvoidanceFactor);
+        return this;
+    }
+
+    public RedeliveryPolicyType initialRedeliveryDelay(long initialRedeliveryDelay) {
+        setInitialRedeliveryDelay(initialRedeliveryDelay);
+        return this;
+    }
+
+    public RedeliveryPolicyType maximumRedeliveries(int maximumRedeliveries) {
+        setMaximumRedeliveries(maximumRedeliveries);
+        return this;
+    }
+
+    public RedeliveryPolicyType useCollisionAvoidance() {
+        setUseCollisionAvoidance(true);
+        return this;
+    }
+
+    public RedeliveryPolicyType useExponentialBackOff() {
+        setUseExponentialBackOff(true);
+        return this;
+    }
+
+
+
+
+    // Properties
+    //-------------------------------------------------------------------------
+
+    public Double getBackOffMultiplier() {
+        return backOffMultiplier;
+    }
+
+    public void setBackOffMultiplier(Double backOffMultiplier) {
+        this.backOffMultiplier = backOffMultiplier;
+    }
+
+    public Double getCollisionAvoidanceFactor() {
+        return collisionAvoidanceFactor;
+    }
+
+    public void setCollisionAvoidanceFactor(Double collisionAvoidanceFactor) {
+        this.collisionAvoidanceFactor = collisionAvoidanceFactor;
+    }
+
+    public Long getInitialRedeliveryDelay() {
+        return initialRedeliveryDelay;
+    }
+
+    public void setInitialRedeliveryDelay(Long initialRedeliveryDelay) {
+        this.initialRedeliveryDelay = initialRedeliveryDelay;
+    }
+
+    public Integer getMaximumRedeliveries() {
+        return maximumRedeliveries;
+    }
+
+    public void setMaximumRedeliveries(Integer maximumRedeliveries) {
+        this.maximumRedeliveries = maximumRedeliveries;
+    }
+
+    public Boolean getUseCollisionAvoidance() {
+        return useCollisionAvoidance;
+    }
+
+    public void setUseCollisionAvoidance(Boolean useCollisionAvoidance) {
+        this.useCollisionAvoidance = useCollisionAvoidance;
+    }
+
+    public Boolean getUseExponentialBackOff() {
+        return useExponentialBackOff;
+    }
+
+    public void setUseExponentialBackOff(Boolean useExponentialBackOff) {
+        this.useExponentialBackOff = useExponentialBackOff;
+    }
+}

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

Modified: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RedeliveryPolicy.java
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RedeliveryPolicy.java?view=diff&rev=565361&r1=565360&r2=565361
==============================================================================
--- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RedeliveryPolicy.java (original)
+++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RedeliveryPolicy.java Mon Aug 13 07:19:30 2007
@@ -113,7 +113,7 @@
     /**
      * Enables collision avoidence and sets the percentage used
      */
-    public RedeliveryPolicy collisionAvoidancePercent(short collisionAvoidancePercent) {
+    public RedeliveryPolicy collisionAvoidancePercent(double collisionAvoidancePercent) {
         useCollisionAvoidance();
         setCollisionAvoidancePercent(collisionAvoidancePercent);
         return this;
@@ -141,7 +141,7 @@
      * Sets the percentage used for collision avoidence if enabled via
      * {@link #setUseCollisionAvoidance(boolean)}
      */
-    public void setCollisionAvoidancePercent(short collisionAvoidancePercent) {
+    public void setCollisionAvoidancePercent(double collisionAvoidancePercent) {
         this.collisionAvoidanceFactor = collisionAvoidancePercent * 0.01d;
     }
 

Modified: activemq/camel/trunk/camel-core/src/main/resources/org/apache/camel/model/jaxb.index
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/resources/org/apache/camel/model/jaxb.index?view=diff&rev=565361&r1=565360&r2=565361
==============================================================================
--- activemq/camel/trunk/camel-core/src/main/resources/org/apache/camel/model/jaxb.index (original)
+++ activemq/camel/trunk/camel-core/src/main/resources/org/apache/camel/model/jaxb.index Mon Aug 13 07:19:30 2007
@@ -32,6 +32,7 @@
 ProceedType
 ProcessorRef
 RecipientListType
+RedeliveryPolicyType
 ResequencerType
 RouteType
 RoutesType

Copied: activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RedeliveryPolicyPerExceptionTest.java (from r565311, activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelTest.java)
URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RedeliveryPolicyPerExceptionTest.java?view=diff&rev=565361&p1=activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelTest.java&r1=565311&p2=activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RedeliveryPolicyPerExceptionTest.java&r2=565361
==============================================================================
--- activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/DeadLetterChannelTest.java (original)
+++ activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/RedeliveryPolicyPerExceptionTest.java Mon Aug 13 07:19:30 2007
@@ -17,91 +17,83 @@
 package org.apache.camel.processor;
 
 import org.apache.camel.ContextTestSupport;
-import org.apache.camel.Endpoint;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
+import org.apache.camel.Message;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 
-import static org.apache.camel.component.mock.MockEndpoint.assertIsSatisfied;
+import java.util.List;
 
 /**
  * @version $Revision: 1.1 $
  */
-public class DeadLetterChannelTest extends ContextTestSupport {
-    protected Endpoint<Exchange> startEndpoint;
-    protected MockEndpoint deadEndpoint; 
-    protected MockEndpoint successEndpoint;
-    protected int failUntilAttempt = 2;
-    protected String body = "<hello>world!</hello>";
-
-    public void testFirstFewAttemptsFail() throws Exception {
-        successEndpoint.expectedBodiesReceived(body);
-        successEndpoint.message(0).header(DeadLetterChannel.REDELIVERED).isEqualTo(true);
-        // TODO convert to AND
-        successEndpoint.message(0).header(DeadLetterChannel.REDELIVERY_COUNTER).isEqualTo(1);
+public class RedeliveryPolicyPerExceptionTest extends ContextTestSupport {
+    protected MockEndpoint a;
+    protected MockEndpoint b;
 
-        deadEndpoint.expectedMessageCount(0);
+    public void testUsingCustomExceptionHandlerAndOneRedelivery() throws Exception {
+        a.expectedMessageCount(1);
 
-        sendBody("direct:start", body);
+        sendBody("direct:start", "a");
 
-        assertIsSatisfied(deadEndpoint, successEndpoint);
+        MockEndpoint.assertIsSatisfied(a, b);
+
+        List<Exchange> list = a.getReceivedExchanges();
+        assertTrue("List should not be empty!", !list.isEmpty());
+        Exchange exchange = list.get(0);
+        Message in = exchange.getIn();
+        log.info("Found message with headers: " + in.getHeaders());
+
+        assertMessageHeader(in, DeadLetterChannel.REDELIVERY_COUNTER, 2);
+        assertMessageHeader(in, DeadLetterChannel.REDELIVERED, true);
     }
 
-    public void testLotsOfAttemptsFail() throws Exception {
-        failUntilAttempt = 5;
+    public void testUsingCustomExceptionHandlerWithNoRedeliveries() throws Exception {
+        b.expectedMessageCount(1);
+
+        sendBody("direct:start", "b");
 
-        deadEndpoint.expectedBodiesReceived(body);
-        deadEndpoint.message(0).header(DeadLetterChannel.REDELIVERED).isEqualTo(true);
-        // TODO convert to AND
-        deadEndpoint.message(0).header(DeadLetterChannel.REDELIVERY_COUNTER).isEqualTo(2);
-        successEndpoint.expectedMessageCount(0);
+        MockEndpoint.assertIsSatisfied(a, b);
 
-        sendBody("direct:start", body);
 
-        assertIsSatisfied(deadEndpoint, successEndpoint);
+        List<Exchange> list = b.getReceivedExchanges();
+        assertTrue("List should not be empty!", !list.isEmpty());
+        Exchange exchange = list.get(0);
+        Message in = exchange.getIn();
+        log.info("Found message with headers: " + in.getHeaders());
+
+        assertMessageHeader(in, DeadLetterChannel.REDELIVERY_COUNTER, 1);
+        assertMessageHeader(in, DeadLetterChannel.REDELIVERED, true);
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-
-        deadEndpoint = (MockEndpoint)resolveMandatoryEndpoint("mock:failed");
-        successEndpoint = (MockEndpoint)resolveMandatoryEndpoint("mock:success");
+        a = resolveMandatoryEndpoint("mock:a", MockEndpoint.class);
+        b = resolveMandatoryEndpoint("mock:b", MockEndpoint.class);
     }
 
     protected RouteBuilder createRouteBuilder() {
+
         final Processor processor = new Processor() {
             public void process(Exchange exchange) {
-                Integer counter = exchange.getIn().getHeader(DeadLetterChannel.REDELIVERY_COUNTER,
-                                                             Integer.class);
-                int attempt = (counter == null) ? 1 : counter + 1;
-                if (attempt < failUntilAttempt) {
-                    throw new RuntimeException("Failed to process due to attempt: " + attempt
-                                               + " being less than: " + failUntilAttempt);
-                } else {
-                    template.send("mock:success", exchange);
+                if ("b".equals(exchange.getIn().getBody())) {
+                    throw new NullPointerException("MyCustomException");
+                }
+                else {
+                    throw new IllegalArgumentException("MyCustomException");
                 }
             }
         };
 
         return new RouteBuilder() {
             public void configure() {
-                from("direct:start").errorHandler(
-                                                  deadLetterChannel("mock:failed").maximumRedeliveries(2)
-                                                      .initialRedeliveryDelay(1)
-                                                      .loggingLevel(LoggingLevel.DEBUG)
-
-                ).process(processor);
-
-                /*
-                 * TODO - currently process().to() results in two separate
-                 * operations which have their own error handler
-                 * 
-                 * .to("mock:success");
-                 */
+                exception(IllegalArgumentException.class).maximumRedeliveries(2).to("mock:a");
+                exception(NullPointerException.class).to("mock:b");
+
+                from("direct:start").process(processor);
             }
         };
     }
-
-}
+}
\ No newline at end of file