You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ni...@apache.org on 2010/05/28 13:49:56 UTC

svn commit: r949153 - in /camel/trunk/camel-core/src: main/java/org/apache/camel/ main/java/org/apache/camel/component/bean/ main/java/org/apache/camel/processor/ main/java/org/apache/camel/util/ test/java/org/apache/camel/processor/routingslip/

Author: ningjiang
Date: Fri May 28 11:49:56 2010
New Revision: 949153

URL: http://svn.apache.org/viewvc?rev=949153&view=rev
Log:
CAMEL-1372, CAMEL-2704 Added the RoutingSlip annotation and Let RoutingSlip support expression

Added:
    camel/trunk/camel-core/src/main/java/org/apache/camel/RoutingSlip.java   (with props)
    camel/trunk/camel-core/src/test/java/org/apache/camel/processor/routingslip/RoutingSlipPOJOTest.java   (with props)
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RoutingSlip.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/util/ExchangeHelper.java

Added: camel/trunk/camel-core/src/main/java/org/apache/camel/RoutingSlip.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/RoutingSlip.java?rev=949153&view=auto
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/RoutingSlip.java (added)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/RoutingSlip.java Fri May 28 11:49:56 2010
@@ -0,0 +1,50 @@
+/**
+ * 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;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that this method is to be used as a 
+ * <a href="http://camel.apache.org/routing-slip.html">Routing Slip</a> routing the incoming message
+ * through a series of processing steps.
+ *
+ * When a message {@link org.apache.camel.Exchange} is received from an {@link org.apache.camel.Endpoint} then the
+ * <a href="http://camel.apache.org/bean-integration.html">Bean Integration</a>
+ * mechanism is used to map the incoming {@link org.apache.camel.Message} to the method parameters.
+ *
+ * The return value of the method is then converted to either a {@link java.util.Collection} or array of objects where each
+ * element is converted to an {@link Endpoint} or a {@link String}, or if it is not a collection/array then it is converted
+ * to an {@link Endpoint} or {@link String}.
+ *
+ * Then for each endpoint or URI the message is forwarded a separate copy.
+ *
+ * @version $Revision$
+ */
+
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Target({ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR })
+public @interface RoutingSlip {
+    String context() default "";
+    String delimiter() default ",";
+    boolean ignoreInvalidEndpoints() default false;
+}

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

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

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java?rev=949153&r1=949152&r2=949153&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java Fri May 28 11:49:56 2010
@@ -33,6 +33,7 @@ import org.apache.camel.Expression;
 import org.apache.camel.NoTypeConversionAvailableException;
 import org.apache.camel.Pattern;
 import org.apache.camel.processor.RecipientList;
+import org.apache.camel.processor.RoutingSlip;
 import org.apache.camel.processor.aggregate.AggregationStrategy;
 import org.apache.camel.util.CamelContextHelper;
 import org.apache.camel.util.ObjectHelper;
@@ -60,6 +61,7 @@ public class MethodInfo {
     private Expression parametersExpression;
     private ExchangePattern pattern = ExchangePattern.InOut;
     private RecipientList recipientList;
+    private RoutingSlip routingSlip;
 
     public MethodInfo(CamelContext camelContext, Class<?> type, Method method, List<ParameterInfo> parameters, List<ParameterInfo> bodyParameters,
                       boolean hasCustomAnnotation, boolean hasHandlerAnnotation) {
@@ -76,6 +78,20 @@ public class MethodInfo {
         if (oneway != null) {
             pattern = oneway.value();
         }
+        
+        if (method.getAnnotation(org.apache.camel.RoutingSlip.class) != null
+                && matchContext(method.getAnnotation(org.apache.camel.RoutingSlip.class).context())) {
+            org.apache.camel.RoutingSlip annotation = method.getAnnotation(org.apache.camel.RoutingSlip.class);
+            routingSlip = new RoutingSlip(camelContext);
+            routingSlip.setDelimiter(annotation.delimiter());
+            routingSlip.setIgnoreInvalidEndpoints(annotation.ignoreInvalidEndpoints());
+            // add created recipientList as a service so we have its lifecycle managed
+            try {
+                camelContext.addService(routingSlip);
+            } catch (Exception e) {
+                throw ObjectHelper.wrapRuntimeCamelException(e);
+            }
+        }
 
         if (method.getAnnotation(org.apache.camel.RecipientList.class) != null
                 && matchContext(method.getAnnotation(org.apache.camel.RecipientList.class).context())) {
@@ -154,6 +170,13 @@ public class MethodInfo {
                     // return Void to indicate to BeanProcessor that there is no reply
                     return Void.TYPE;
                 }
+                if (routingSlip != null) {
+                    if (!routingSlip.isStarted()) {
+                        ServiceHelper.startService(routingSlip);
+                    }
+                    routingSlip.doRoutingSlip(exchange, result);
+                    return Void.TYPE;
+                }
                 return result;
             }
 

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RoutingSlip.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RoutingSlip.java?rev=949153&r1=949152&r2=949153&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RoutingSlip.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/RoutingSlip.java Fri May 28 11:49:56 2010
@@ -16,15 +16,19 @@
  */
 package org.apache.camel.processor;
 
+import java.util.Iterator;
+
 import org.apache.camel.CamelContext;
 import org.apache.camel.Endpoint;
 import org.apache.camel.Exchange;
 import org.apache.camel.ExchangePattern;
+import org.apache.camel.Expression;
 import org.apache.camel.FailedToCreateProducerException;
 import org.apache.camel.Message;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
 import org.apache.camel.ProducerCallback;
+import org.apache.camel.builder.ExpressionBuilder;
 import org.apache.camel.impl.DefaultExchange;
 import org.apache.camel.impl.ProducerCache;
 import org.apache.camel.impl.ServiceSupport;
@@ -46,14 +50,23 @@ public class RoutingSlip extends Service
     private static final transient Log LOG = LogFactory.getLog(RoutingSlip.class);
     private ProducerCache producerCache;
     private boolean ignoreInvalidEndpoints;
-    private final String header;
-    private final String uriDelimiter;
+    private String header;
+    private Expression expression;    
+    private String uriDelimiter;
     private final CamelContext camelContext;
+    
+    public RoutingSlip(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
 
+    // This method will be replaced by the construction method with the expression
+    @Deprecated
     public RoutingSlip(CamelContext camelContext, String header) {
         this(camelContext, header, RoutingSlipDefinition.DEFAULT_DELIMITER);
     }
 
+ // This method will be replaced by the construction method with the expression
+    @Deprecated
     public RoutingSlip(CamelContext camelContext, String header, String uriDelimiter) {
         notNull(camelContext, "camelContext");
         notNull(header, "header");
@@ -61,7 +74,22 @@ public class RoutingSlip extends Service
 
         this.camelContext = camelContext;
         this.header = header;
+        expression = ExpressionBuilder.headerExpression(header);
+        this.uriDelimiter = uriDelimiter;
+    }
+    
+    public RoutingSlip(CamelContext camelContext, Expression expression, String uriDelimiter) {
+        notNull(camelContext, "camelContext");
+        notNull(expression, "expression");
+        
+        this.camelContext = camelContext;
+        this.expression = expression;
         this.uriDelimiter = uriDelimiter;
+        this.header = null;
+    }
+    
+    public void setDelimiter(String delimiter) {
+        this.uriDelimiter = delimiter;
     }
     
     public boolean isIgnoreInvalidEndpoints() {
@@ -74,26 +102,31 @@ public class RoutingSlip extends Service
 
     @Override
     public String toString() {
-        return "RoutingSlip[header=" + header + " uriDelimiter=" + uriDelimiter + "]";
+        return "RoutingSlip[expression=" + expression + " uriDelimiter=" + uriDelimiter + "]";
     }
 
     public String getTraceLabel() {
-        return "routingSlip[" + header + "]";
+        return "routingSlip[" + expression + "]";
     }
 
     public void process(Exchange exchange) throws Exception {
         if (!isStarted()) {
             throw new IllegalStateException("RoutingSlip has not been started: " + this);
-        }
-
-        Message message = exchange.getIn();
-        String[] recipients = recipients(message);
+        }        
+       
+        Object routingSlip = expression.evaluate(exchange, Object.class);
+        doRoutingSlip(exchange, routingSlip);        
+    }
+    
+    public void doRoutingSlip(Exchange exchange, Object routingSlip) throws Exception {
+        Iterator<Object> iter = ObjectHelper.createIterator(routingSlip, uriDelimiter);
         Exchange current = exchange;
 
-        for (String nextRecipient : recipients) {
+        while (iter.hasNext()) {
+            Object nextRecipient = iter.next();
             Endpoint endpoint;
             try {
-                endpoint = resolveEndpoint(exchange, nextRecipient.trim());
+                endpoint = resolveEndpoint(exchange, nextRecipient);
             } catch (Exception e) {
                 if (isIgnoreInvalidEndpoints()) {
                     LOG.info("Endpoint uri is invalid: " + nextRecipient + ". This exception will be ignored.", e);
@@ -104,7 +137,7 @@ public class RoutingSlip extends Service
             }
 
             Exchange copy = new DefaultExchange(current);
-            updateRoutingSlip(current);
+            updateRoutingSlipHeader(current);
             copyOutToIn(copy, current);
 
             try {                
@@ -178,16 +211,19 @@ public class RoutingSlip extends Service
         ServiceHelper.stopService(producerCache);
     }
 
-    private void updateRoutingSlip(Exchange current) {
-        Message message = getResultMessage(current);
-        String oldSlip = message.getHeader(header, String.class);
-        if (oldSlip != null) {
-            int delimiterIndex = oldSlip.indexOf(uriDelimiter);
-            String newSlip = delimiterIndex > 0 ? oldSlip.substring(delimiterIndex + 1) : "";
-            message.setHeader(header, newSlip);
+    private void updateRoutingSlipHeader(Exchange current) {
+        // only update the header value which used as the routingslip
+        if (header != null) {
+            Message message = getResultMessage(current);
+            String oldSlip = message.getHeader(header, String.class);
+            if (oldSlip != null) {
+                int delimiterIndex = oldSlip.indexOf(uriDelimiter);
+                String newSlip = delimiterIndex > 0 ? oldSlip.substring(delimiterIndex + 1) : "";
+                message.setHeader(header, newSlip);
+            }
         }
     }
-
+    
     /**
      * Returns the outbound message if available. Otherwise return the inbound
      * message.
@@ -201,17 +237,7 @@ public class RoutingSlip extends Service
         }
     }
 
-    /**
-     * Return the list of recipients defined in the routing slip in the
-     * specified message.
-     */
-    private String[] recipients(Message message) {
-        Object headerValue = message.getHeader(header);
-        if (ObjectHelper.isNotEmpty(headerValue)) {
-            return headerValue.toString().split(uriDelimiter);
-        }
-        return new String[]{};
-    }
+    
 
     /**
      * Copy the outbound data in 'source' to the inbound data in 'result'.

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/ExchangeHelper.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/ExchangeHelper.java?rev=949153&r1=949152&r2=949153&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/util/ExchangeHelper.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/ExchangeHelper.java Fri May 28 11:49:56 2010
@@ -78,7 +78,7 @@ public final class ExchangeHelper {
         if (value instanceof Endpoint) {
             endpoint = (Endpoint)value;
         } else {
-            String uri = value.toString();
+            String uri = value.toString().trim();
             endpoint = CamelContextHelper.getMandatoryEndpoint(exchange.getContext(), uri);
         }
         return endpoint;

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/routingslip/RoutingSlipPOJOTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/routingslip/RoutingSlipPOJOTest.java?rev=949153&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/routingslip/RoutingSlipPOJOTest.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/routingslip/RoutingSlipPOJOTest.java Fri May 28 11:49:56 2010
@@ -0,0 +1,66 @@
+/**
+ * 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.routingslip;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.RoutingSlip;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+
+public class RoutingSlipPOJOTest extends ContextTestSupport {
+    
+    public void testRoutingSlipPOJO() throws Exception {
+        MockEndpoint foo = getMockEndpoint("mock:foo");
+        MockEndpoint result = getMockEndpoint("mock:result");
+        
+        foo.expectedBodiesReceived("Message");
+        result.expectedBodiesReceived("Message is processed!");       
+
+        template.sendBody("direct:a", "Message");
+
+        assertMockEndpointsSatisfied();
+    }
+    
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                
+                from("direct:a").bean(new MyRoutingSlipPOJO());
+                
+                from("direct:b").process(new Processor() {
+
+                    public void process(Exchange exchange) throws Exception {
+                        exchange.getOut().setBody(exchange.getIn().getBody() + " is processed!");                        
+                    }
+                    
+                });
+            }
+        };
+    }
+    
+    public class MyRoutingSlipPOJO {
+        @RoutingSlip(context = "camel-1")
+        public String[] doSomething(String body) {
+            return new String[]{"mock:foo", "direct:b", "mock:result"};
+        }
+    }
+    
+    
+
+}

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

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