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