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 2012/01/05 10:00:28 UTC

svn commit: r1227529 - in /camel/trunk/camel-core/src: main/java/org/apache/camel/ main/java/org/apache/camel/impl/ main/java/org/apache/camel/model/ test/java/org/apache/camel/processor/intercept/

Author: davsclaus
Date: Thu Jan  5 09:00:27 2012
New Revision: 1227529

URL: http://svn.apache.org/viewvc?rev=1227529&view=rev
Log:
CAMEL-4809: Fixed interceptSendToEndpoint with when predicate and skip option enabled, should only skip sending if the predicate was true. Thanks to Raul for part of this work.

Added:
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/WhenSkipSendToEndpointDefinition.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/processor/intercept/InterceptSendToEndpointConditionalSkipTest.java
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/Exchange.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/InterceptSendToEndpoint.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/ExpressionNode.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/FilterDefinition.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/model/InterceptSendToEndpointDefinition.java

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/Exchange.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/Exchange.java?rev=1227529&r1=1227528&r2=1227529&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/Exchange.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/Exchange.java Thu Jan  5 09:00:27 2012
@@ -136,6 +136,7 @@ public interface Exchange {
     String HTTP_SERVLET_RESPONSE   = "CamelHttpServletResponse";
 
     String INTERCEPTED_ENDPOINT = "CamelInterceptedEndpoint";
+    String INTERCEPT_SEND_TO_ENDPOINT_WHEN_MATCHED = "CamelInterceptSendToEndpointWhenMatched";
 
     String LANGUAGE_SCRIPT          = "CamelLanguageScript";
     String LOG_DEBUG_BODY_MAX_CHARS = "CamelLogDebugBodyMaxChars";

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/InterceptSendToEndpoint.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/InterceptSendToEndpoint.java?rev=1227529&r1=1227528&r2=1227529&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/InterceptSendToEndpoint.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/InterceptSendToEndpoint.java Thu Jan  5 09:00:27 2012
@@ -73,6 +73,7 @@ public class InterceptSendToEndpoint imp
     public EndpointConfiguration getEndpointConfiguration() {
         return delegate.getEndpointConfiguration();
     }
+
     public String getEndpointKey() {
         return delegate.getEndpointKey();
     }
@@ -133,7 +134,16 @@ public class InterceptSendToEndpoint imp
                     return;
                 }
 
-                if (!skip) {
+                // determine if we should skip or not
+                boolean shouldSkip = skip;
+
+                // if then interceptor had a when predicate, then we should only skip if it matched
+                Boolean whenMatches = (Boolean) exchange.removeProperty(Exchange.INTERCEPT_SEND_TO_ENDPOINT_WHEN_MATCHED);
+                if (whenMatches != null) {
+                    shouldSkip = skip && whenMatches;
+                }
+
+                if (!shouldSkip) {
                     if (exchange.hasOut()) {
                         // replace OUT with IN as detour changed something
                         exchange.setIn(exchange.getOut());

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/ExpressionNode.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/ExpressionNode.java?rev=1227529&r1=1227528&r2=1227529&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/ExpressionNode.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/ExpressionNode.java Thu Jan  5 09:00:27 2012
@@ -97,9 +97,26 @@ public class ExpressionNode extends Proc
         return getExpression().getLabel();
     }
 
+    /**
+     * Creates the {@link FilterProcessor} from the expression node.
+     *
+     * @param routeContext  the route context
+     * @return the created {@link FilterProcessor}
+     * @throws Exception is thrown if error creating the processor
+     */
     protected FilterProcessor createFilterProcessor(RouteContext routeContext) throws Exception {
         Processor childProcessor = this.createChildProcessor(routeContext, false);
-        return new FilterProcessor(getExpression().createPredicate(routeContext), childProcessor);
+        return new FilterProcessor(createPredicate(routeContext), childProcessor);
+    }
+
+    /**
+     * Creates the {@link Predicate} from the expression node.
+     *
+     * @param routeContext  the route context
+     * @return the created predicate
+     */
+    protected Predicate createPredicate(RouteContext routeContext) {
+        return getExpression().createPredicate(routeContext);
     }
 
     @Override

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/FilterDefinition.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/FilterDefinition.java?rev=1227529&r1=1227528&r2=1227529&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/FilterDefinition.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/FilterDefinition.java Thu Jan  5 09:00:27 2012
@@ -61,7 +61,6 @@ public class FilterDefinition extends Ex
         return "filter";
     }
 
-
     @Override
     public FilterProcessor createProcessor(RouteContext routeContext) throws Exception {
         return createFilterProcessor(routeContext);
@@ -71,7 +70,7 @@ public class FilterDefinition extends Ex
     protected FilterProcessor createFilterProcessor(RouteContext routeContext) throws Exception {
         // filter EIP should have child outputs
         Processor childProcessor = this.createChildProcessor(routeContext, true);
-        return new FilterProcessor(getExpression().createPredicate(routeContext), childProcessor);
+        return new FilterProcessor(createPredicate(routeContext), childProcessor);
     }
 
 }

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/InterceptSendToEndpointDefinition.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/InterceptSendToEndpointDefinition.java?rev=1227529&r1=1227528&r2=1227529&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/InterceptSendToEndpointDefinition.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/InterceptSendToEndpointDefinition.java Thu Jan  5 09:00:27 2012
@@ -87,14 +87,13 @@ public class InterceptSendToEndpointDefi
         // register endpoint callback so we can proxy the endpoint
         routeContext.getCamelContext().addRegisterEndpointCallback(new EndpointStrategy() {
             public Endpoint registerEndpoint(String uri, Endpoint endpoint) {
-                
                 if (endpoint instanceof InterceptSendToEndpoint) {
                     // endpoint already decorated
                     return endpoint;
                 } else if (getUri() == null || EndpointHelper.matchEndpoint(uri, getUri())) {
                     // only proxy if the uri is matched decorate endpoint with our proxy
                     // should be false by default
-                    boolean skip = getSkipSendToOriginalEndpoint() != null ? getSkipSendToOriginalEndpoint() : false;
+                    boolean skip = isSkipSendToOriginalEndpoint();
                     InterceptSendToEndpoint proxy = new InterceptSendToEndpoint(endpoint, skip);
                     proxy.setDetour(detour);
                     return proxy;
@@ -153,19 +152,30 @@ public class InterceptSendToEndpointDefi
             return;
         }
 
+        // if there is a when definition at first, then its a predicate for this interceptor
         ProcessorDefinition first = getOutputs().get(0);
-        if (first instanceof WhenDefinition) {
+        if (first instanceof WhenDefinition && !(first instanceof WhenSkipSendToEndpointDefinition)) {
             WhenDefinition when = (WhenDefinition) first;
+
+            // create a copy of when to use as replacement
+            WhenSkipSendToEndpointDefinition newWhen = new WhenSkipSendToEndpointDefinition();
+            newWhen.setExpression(when.getExpression());
+            newWhen.setId(when.getId());
+            newWhen.setInheritErrorHandler(when.isInheritErrorHandler());
+            newWhen.setParent(when.getParent());
+            newWhen.setOtherAttributes(when.getOtherAttributes());
+            newWhen.setNodeFactory(when.getNodeFactory());
+            newWhen.setDescription(when.getDescription());
+
             // move this outputs to the when, expect the first one
             // as the first one is the interceptor itself
             for (int i = 1; i < outputs.size(); i++) {
                 ProcessorDefinition out = outputs.get(i);
-                when.addOutput(out);
+                newWhen.addOutput(out);
             }
             // remove the moved from the original output, by just keeping the first one
-            ProcessorDefinition keep = outputs.get(0);
             clearOutput();
-            outputs.add(keep);
+            outputs.add(newWhen);
         }
     }
 
@@ -176,6 +186,10 @@ public class InterceptSendToEndpointDefi
     public void setSkipSendToOriginalEndpoint(Boolean skipSendToOriginalEndpoint) {
         this.skipSendToOriginalEndpoint = skipSendToOriginalEndpoint;
     }
+    
+    public boolean isSkipSendToOriginalEndpoint() {
+        return skipSendToOriginalEndpoint != null && skipSendToOriginalEndpoint;
+    }
 
     public String getUri() {
         return uri;

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/model/WhenSkipSendToEndpointDefinition.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/WhenSkipSendToEndpointDefinition.java?rev=1227529&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/model/WhenSkipSendToEndpointDefinition.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/WhenSkipSendToEndpointDefinition.java Thu Jan  5 09:00:27 2012
@@ -0,0 +1,48 @@
+/**
+ * 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.Exchange;
+import org.apache.camel.Predicate;
+import org.apache.camel.spi.RouteContext;
+
+/**
+ *
+ */
+public class WhenSkipSendToEndpointDefinition extends WhenDefinition {
+
+    @Override
+    protected Predicate createPredicate(RouteContext routeContext) {
+        // we need to keep track whether the when matches or not, so delegate
+        // the predicate and add the matches result as a property on the exchange
+        final Predicate delegate = super.createPredicate(routeContext);
+        return new Predicate() {
+            @Override
+            public boolean matches(Exchange exchange) {
+                boolean matches = delegate.matches(exchange);
+                exchange.setProperty(Exchange.INTERCEPT_SEND_TO_ENDPOINT_WHEN_MATCHED, matches);
+                return matches;
+            }
+
+            @Override
+            public String toString() {
+                return delegate.toString();
+            }
+        };
+    }
+
+}

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/intercept/InterceptSendToEndpointConditionalSkipTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/intercept/InterceptSendToEndpointConditionalSkipTest.java?rev=1227529&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/intercept/InterceptSendToEndpointConditionalSkipTest.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/intercept/InterceptSendToEndpointConditionalSkipTest.java Thu Jan  5 09:00:27 2012
@@ -0,0 +1,129 @@
+/**
+ * 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.intercept;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+
+/**
+ * Unit tests on the conditional skip support on InterceptSendToEndpoint.
+ * 
+ * @version
+ */
+public class InterceptSendToEndpointConditionalSkipTest extends ContextTestSupport {
+
+    /**
+     * Verify that the endpoint is only skipped if the adjacent 'when' condition is satisfied
+     */
+    public void testInterceptSendToEndpointSkipConditionSatisfied() throws Exception {
+        getMockEndpoint("mock:a").expectedMessageCount(1);
+        getMockEndpoint("mock:skippable").expectedMessageCount(0);
+        getMockEndpoint("mock:detour").expectedMessageCount(1);
+        getMockEndpoint("mock:c").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "skip");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    /**
+     * Verify that the endpoint is not skipped if the adjacent 'when' condition evaluates to false
+     */
+    public void testInterceptSendToEndpointSkipConditionNotSatisfied() throws Exception {
+        getMockEndpoint("mock:a").expectedMessageCount(1);
+        getMockEndpoint("mock:skippable").expectedMessageCount(1);
+        getMockEndpoint("mock:detour").expectedMessageCount(0);
+        getMockEndpoint("mock:c").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    /**
+     * Verify that the conditional skip support is only activated when using interceptSendToEndpoint().when() and not
+     * interceptSendToEndpoint().choice()..., as the choice keyword is not directly associated with the interception behaviour and it belongs to the
+     * interception body (initiating a new routing block)
+     */
+    public void testInterceptSendToEndpointSkipConditionNoEffectChoice() throws Exception {
+        getMockEndpoint("mock:a").expectedMessageCount(2);
+        getMockEndpoint("mock:skippableNoEffect").expectedMessageCount(0);
+        getMockEndpoint("mock:c").expectedMessageCount(2);
+
+        getMockEndpoint("mock:noSkipWhen").expectedMessageCount(1);
+        getMockEndpoint("mock:noSkipOW").expectedMessageCount(1);
+
+        template.sendBody("direct:startNoEffect", "skipNoEffectWhen");
+        template.sendBody("direct:startNoEffect", "Hello Camel");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    /**
+     * Test that when multiple conditions are chained together in Java DSL, only the first one will determine whether the endpoint is skipped or not
+     */
+    public void testInterceptSendToEndpointSkipMultipleConditions() throws Exception {
+        getMockEndpoint("mock:a").expectedMessageCount(1);
+        getMockEndpoint("mock:skippableMultipleConditions").expectedMessageCount(0);
+        getMockEndpoint("mock:detour").expectedMessageCount(1);
+        getMockEndpoint("mock:c").expectedMessageCount(1);
+
+        template.sendBody("direct:startMultipleConditions", "skip");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // only skip if the body equals 'skip'
+                interceptSendToEndpoint("mock:skippable").skipSendToOriginalEndpoint()
+                        .when(body().isEqualTo("skip")).to("mock:detour");
+
+                // always skip with a normal with a normal choice inside instructing where to route instead
+                interceptSendToEndpoint("mock:skippableNoEffect").skipSendToOriginalEndpoint()
+                        .choice()
+                        .when(body().isEqualTo("skipNoEffectWhen")).to("mock:noSkipWhen")
+                        .otherwise().to("mock:noSkipOW");
+
+                // in this case, the original endpoint will be skipped but no message will be sent to mock:detour
+                interceptSendToEndpoint("mock:skippableMultipleConditions").skipSendToOriginalEndpoint()
+                        .when(body().isEqualTo("skip"))
+                        .when(body().isNotEqualTo("skip"))
+                            .to("mock:detour");
+
+                from("direct:start")
+                        .to("mock:a")
+                        .to("mock:skippable")
+                        .to("mock:c");
+
+                from("direct:startNoEffect")
+                        .to("mock:a")
+                        .to("mock:skippableNoEffect")
+                        .to("mock:c");
+
+                from("direct:startMultipleConditions")
+                        .to("mock:a")
+                        .to("mock:skippableMultipleConditions")
+                        .to("mock:c");
+            }
+        };
+    }
+
+}