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 2013/08/26 11:50:09 UTC

[1/2] git commit: CAMEL-6291: Fixed to not share the routes between the s as that can cause side-effects.

Updated Branches:
  refs/heads/camel-2.11.x 9938a4de4 -> f85ca1d00
  refs/heads/master 5721e40ef -> cfa3b5f53


CAMEL-6291: Fixed <routeContextRef> to not share the routes between the <camelContext>s as that can cause side-effects.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/cfa3b5f5
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/cfa3b5f5
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/cfa3b5f5

Branch: refs/heads/master
Commit: cfa3b5f534651d844843a3d0599ef34caf9db6f5
Parents: 5721e40
Author: Claus Ibsen <da...@apache.org>
Authored: Mon Aug 26 11:09:06 2013 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Mon Aug 26 11:49:08 2013 +0200

----------------------------------------------------------------------
 .../camel/model/RouteContextRefDefinition.java  |  11 +-
 .../model/RouteContextRefDefinitionHelper.java  | 135 +++++++++++++++++++
 ...PlaceholderMultipleCamelContextRefsTest.java |  61 +++++++++
 .../src/test/resources/mycamel-1.properties     |  18 +++
 .../src/test/resources/mycamel-2.properties     |  18 +++
 ...yPlaceholderMultipleCamelContextRefsTest.xml |  42 ++++++
 6 files changed, 275 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/cfa3b5f5/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinition.java b/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinition.java
index 12e59cf..87667a3 100644
--- a/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinition.java
@@ -23,8 +23,6 @@ import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlRootElement;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.util.CamelContextHelper;
-import org.apache.camel.util.ObjectHelper;
 
 /**
  * Represents an XML &lt;routeContextRef/&gt; element
@@ -55,14 +53,7 @@ public class RouteContextRefDefinition {
 
     @SuppressWarnings({"unchecked", "rawtypes"})
     public List<RouteDefinition> lookupRoutes(CamelContext camelContext) {
-        ObjectHelper.notNull(camelContext, "camelContext", this);
-        ObjectHelper.notNull(ref, "ref", this);
-
-        List answer = CamelContextHelper.lookup(camelContext, ref, List.class);
-        if (answer == null) {
-            throw new IllegalArgumentException("Cannot find RouteContext with id " + ref);
-        }
-        return answer;
+        return RouteContextRefDefinitionHelper.lookupRoutes(camelContext, ref);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/cfa3b5f5/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinitionHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinitionHelper.java b/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinitionHelper.java
new file mode 100644
index 0000000..0f69104
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinitionHelper.java
@@ -0,0 +1,135 @@
+/**
+ * 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 java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.model.language.NamespaceAwareExpression;
+import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Helper for {@link RouteContextRefDefinition}.
+ */
+public final class RouteContextRefDefinitionHelper {
+
+    private static JAXBContext jaxbContext;
+
+
+    /**
+     * Lookup the routes from the {@link RouteContextRefDefinition}.
+     * <p/>
+     * This implmementation must be used to lookup the routes as it performs a deep clone of the routes
+     * as a {@link RouteContextRefDefinition} can be re-used with multiple {@link CamelContext} and each
+     * context should have their own instances of the routes. This is to ensure no side-effefts and sharing
+     * of instances between the contexts. For example such as property placeholders may be context specific
+     * so the routes should not use placeholders from another {@link CamelContext}.
+     *
+     * @param camelContext the CamelContext
+     * @param ref          the id of the {@link RouteContextRefDefinition} to lookup and get the rotues.
+     * @return the routes.
+     */
+    public static synchronized List<RouteDefinition> lookupRoutes(CamelContext camelContext, String ref) {
+        ObjectHelper.notNull(camelContext, "camelContext");
+        ObjectHelper.notNull(ref, "ref");
+
+        List<RouteDefinition> answer = CamelContextHelper.lookup(camelContext, ref, List.class);
+        if (answer == null) {
+            throw new IllegalArgumentException("Cannot find RouteContext with id " + ref);
+        }
+
+        // must clone the route definitions as they can be reused with multiple CamelContexts
+        // and they would need their own instances of the definitions to not have side effects among
+        // the CamelContext - for example property placeholder resolutions etc.
+        List<RouteDefinition> clones = new ArrayList<RouteDefinition>(answer.size());
+        try {
+            JAXBContext jaxb = getOrCreateJAXBContext();
+            for (RouteDefinition def : answer) {
+                RouteDefinition clone = cloneRouteDefinition(jaxb, def);
+                if (clone != null) {
+                    clones.add(clone);
+                }
+            }
+        } catch (Exception e) {
+            throw ObjectHelper.wrapRuntimeCamelException(e);
+        }
+
+        return clones;
+    }
+
+    private static synchronized JAXBContext getOrCreateJAXBContext() throws JAXBException {
+        if (jaxbContext == null) {
+            // must use classloader from CamelContext to have JAXB working
+            jaxbContext = JAXBContext.newInstance(Constants.JAXB_CONTEXT_PACKAGES, CamelContext.class.getClassLoader());
+        }
+        return jaxbContext;
+    }
+
+    private static RouteDefinition cloneRouteDefinition(JAXBContext jaxbContext, RouteDefinition def) throws JAXBException {
+        Marshaller marshal = jaxbContext.createMarshaller();
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        marshal.marshal(def, bos);
+
+        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+        Object clone = unmarshaller.unmarshal(bis);
+
+        if (clone != null && clone instanceof RouteDefinition) {
+            RouteDefinition def2 = (RouteDefinition) clone;
+
+            // need to clone the namespaces also as they are not JAXB marshalled (as they are transient)
+            Iterator<ExpressionNode> it = ProcessorDefinitionHelper.filterTypeInOutputs(def.getOutputs(), ExpressionNode.class);
+            Iterator<ExpressionNode> it2 = ProcessorDefinitionHelper.filterTypeInOutputs(def2.getOutputs(), ExpressionNode.class);
+            while (it.hasNext() && it2.hasNext()) {
+                ExpressionNode node = it.next();
+                ExpressionNode node2 = it2.next();
+
+                NamespaceAwareExpression name = null;
+                NamespaceAwareExpression name2 = null;
+                if (node.getExpression() instanceof NamespaceAwareExpression) {
+                    name = (NamespaceAwareExpression) node.getExpression();
+                }
+                if (node2.getExpression() instanceof NamespaceAwareExpression) {
+                    name2 = (NamespaceAwareExpression) node2.getExpression();
+                }
+
+                if (name != null && name2 != null && name.getNamespaces() != null && !name.getNamespaces().isEmpty()) {
+                    Map<String, String> map = new HashMap<String, String>();
+                    map.putAll(name.getNamespaces());
+                    name2.setNamespaces(map);
+                }
+            }
+
+            return def2;
+        }
+
+        return null;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/cfa3b5f5/components/camel-spring/src/test/java/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.java
----------------------------------------------------------------------
diff --git a/components/camel-spring/src/test/java/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.java b/components/camel-spring/src/test/java/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.java
new file mode 100644
index 0000000..4d953cb
--- /dev/null
+++ b/components/camel-spring/src/test/java/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.java
@@ -0,0 +1,61 @@
+/**
+ * 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.spring.config;
+
+import junit.framework.TestCase;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.springframework.context.support.AbstractXmlApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * @version 
+ */
+public class RouteRefPropertyPlaceholderMultipleCamelContextRefsTest extends TestCase {
+
+    protected AbstractXmlApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.xml");
+    }
+
+    public void testSpringTwoCamelContextDirectEndpoint() throws Exception {
+        AbstractXmlApplicationContext ac = createApplicationContext();
+        ac.start();
+
+        CamelContext camel1 = ac.getBean("myCamel-1", CamelContext.class);
+        CamelContext camel2 = ac.getBean("myCamel-2", CamelContext.class);
+
+        Endpoint start1 = camel1.getEndpoint("direct:start");
+        Endpoint start2 = camel2.getEndpoint("direct:start");
+        assertNotSame(start1, start2);
+        
+        MockEndpoint mock1 = camel1.getEndpoint("mock:end-1", MockEndpoint.class);
+        mock1.expectedBodiesReceived("Hello World");
+
+        MockEndpoint mock2 = camel2.getEndpoint("mock:end-2", MockEndpoint.class);
+        mock2.expectedBodiesReceived("Bye World");
+
+        camel1.createProducerTemplate().sendBody("direct:start", "Hello World");
+        camel2.createProducerTemplate().sendBody("direct:start", "Bye World");
+
+        mock1.assertIsSatisfied();
+        mock2.assertIsSatisfied();
+
+        ac.stop();
+    }
+    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/cfa3b5f5/components/camel-spring/src/test/resources/mycamel-1.properties
----------------------------------------------------------------------
diff --git a/components/camel-spring/src/test/resources/mycamel-1.properties b/components/camel-spring/src/test/resources/mycamel-1.properties
new file mode 100644
index 0000000..508e0dc
--- /dev/null
+++ b/components/camel-spring/src/test/resources/mycamel-1.properties
@@ -0,0 +1,18 @@
+## ------------------------------------------------------------------------
+## 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.
+## ------------------------------------------------------------------------
+
+end=mock:end-1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/cfa3b5f5/components/camel-spring/src/test/resources/mycamel-2.properties
----------------------------------------------------------------------
diff --git a/components/camel-spring/src/test/resources/mycamel-2.properties b/components/camel-spring/src/test/resources/mycamel-2.properties
new file mode 100644
index 0000000..34fecb9
--- /dev/null
+++ b/components/camel-spring/src/test/resources/mycamel-2.properties
@@ -0,0 +1,18 @@
+## ------------------------------------------------------------------------
+## 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.
+## ------------------------------------------------------------------------
+
+end=mock:end-2
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/cfa3b5f5/components/camel-spring/src/test/resources/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-spring/src/test/resources/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.xml b/components/camel-spring/src/test/resources/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.xml
new file mode 100644
index 0000000..b690aa6
--- /dev/null
+++ b/components/camel-spring/src/test/resources/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+
+  <routeContext id="myCoolRoute" xmlns="http://camel.apache.org/schema/spring">
+    <route id="cool">
+      <from uri="direct:start"/>
+      <to uri="{{end}}"/>
+    </route>
+  </routeContext>
+
+  <camelContext id="myCamel-1" xmlns="http://camel.apache.org/schema/spring">
+    <propertyPlaceholder id="properties1" location="mycamel-1.properties"/>
+    <routeContextRef ref="myCoolRoute"/>
+  </camelContext>
+
+  <camelContext id="myCamel-2" xmlns="http://camel.apache.org/schema/spring">
+    <propertyPlaceholder id="properties2" location="mycamel-2.properties"/>
+    <routeContextRef ref="myCoolRoute"/>
+  </camelContext>
+
+</beans>


[2/2] git commit: CAMEL-6291: Fixed to not share the routes between the s as that can cause side-effects.

Posted by da...@apache.org.
CAMEL-6291: Fixed <routeContextRef> to not share the routes between the <camelContext>s as that can cause side-effects.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/f85ca1d0
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/f85ca1d0
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/f85ca1d0

Branch: refs/heads/camel-2.11.x
Commit: f85ca1d001ef05422e262c7b8e6a7a69ec397e67
Parents: 9938a4d
Author: Claus Ibsen <da...@apache.org>
Authored: Mon Aug 26 11:09:06 2013 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Mon Aug 26 11:49:55 2013 +0200

----------------------------------------------------------------------
 .../camel/model/RouteContextRefDefinition.java  |  11 +-
 .../model/RouteContextRefDefinitionHelper.java  | 135 +++++++++++++++++++
 ...PlaceholderMultipleCamelContextRefsTest.java |  61 +++++++++
 .../src/test/resources/mycamel-1.properties     |  18 +++
 .../src/test/resources/mycamel-2.properties     |  18 +++
 ...yPlaceholderMultipleCamelContextRefsTest.xml |  42 ++++++
 6 files changed, 275 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/f85ca1d0/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinition.java b/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinition.java
index 12e59cf..87667a3 100644
--- a/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinition.java
@@ -23,8 +23,6 @@ import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlRootElement;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.util.CamelContextHelper;
-import org.apache.camel.util.ObjectHelper;
 
 /**
  * Represents an XML &lt;routeContextRef/&gt; element
@@ -55,14 +53,7 @@ public class RouteContextRefDefinition {
 
     @SuppressWarnings({"unchecked", "rawtypes"})
     public List<RouteDefinition> lookupRoutes(CamelContext camelContext) {
-        ObjectHelper.notNull(camelContext, "camelContext", this);
-        ObjectHelper.notNull(ref, "ref", this);
-
-        List answer = CamelContextHelper.lookup(camelContext, ref, List.class);
-        if (answer == null) {
-            throw new IllegalArgumentException("Cannot find RouteContext with id " + ref);
-        }
-        return answer;
+        return RouteContextRefDefinitionHelper.lookupRoutes(camelContext, ref);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/f85ca1d0/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinitionHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinitionHelper.java b/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinitionHelper.java
new file mode 100644
index 0000000..0f69104
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/RouteContextRefDefinitionHelper.java
@@ -0,0 +1,135 @@
+/**
+ * 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 java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.model.language.NamespaceAwareExpression;
+import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Helper for {@link RouteContextRefDefinition}.
+ */
+public final class RouteContextRefDefinitionHelper {
+
+    private static JAXBContext jaxbContext;
+
+
+    /**
+     * Lookup the routes from the {@link RouteContextRefDefinition}.
+     * <p/>
+     * This implmementation must be used to lookup the routes as it performs a deep clone of the routes
+     * as a {@link RouteContextRefDefinition} can be re-used with multiple {@link CamelContext} and each
+     * context should have their own instances of the routes. This is to ensure no side-effefts and sharing
+     * of instances between the contexts. For example such as property placeholders may be context specific
+     * so the routes should not use placeholders from another {@link CamelContext}.
+     *
+     * @param camelContext the CamelContext
+     * @param ref          the id of the {@link RouteContextRefDefinition} to lookup and get the rotues.
+     * @return the routes.
+     */
+    public static synchronized List<RouteDefinition> lookupRoutes(CamelContext camelContext, String ref) {
+        ObjectHelper.notNull(camelContext, "camelContext");
+        ObjectHelper.notNull(ref, "ref");
+
+        List<RouteDefinition> answer = CamelContextHelper.lookup(camelContext, ref, List.class);
+        if (answer == null) {
+            throw new IllegalArgumentException("Cannot find RouteContext with id " + ref);
+        }
+
+        // must clone the route definitions as they can be reused with multiple CamelContexts
+        // and they would need their own instances of the definitions to not have side effects among
+        // the CamelContext - for example property placeholder resolutions etc.
+        List<RouteDefinition> clones = new ArrayList<RouteDefinition>(answer.size());
+        try {
+            JAXBContext jaxb = getOrCreateJAXBContext();
+            for (RouteDefinition def : answer) {
+                RouteDefinition clone = cloneRouteDefinition(jaxb, def);
+                if (clone != null) {
+                    clones.add(clone);
+                }
+            }
+        } catch (Exception e) {
+            throw ObjectHelper.wrapRuntimeCamelException(e);
+        }
+
+        return clones;
+    }
+
+    private static synchronized JAXBContext getOrCreateJAXBContext() throws JAXBException {
+        if (jaxbContext == null) {
+            // must use classloader from CamelContext to have JAXB working
+            jaxbContext = JAXBContext.newInstance(Constants.JAXB_CONTEXT_PACKAGES, CamelContext.class.getClassLoader());
+        }
+        return jaxbContext;
+    }
+
+    private static RouteDefinition cloneRouteDefinition(JAXBContext jaxbContext, RouteDefinition def) throws JAXBException {
+        Marshaller marshal = jaxbContext.createMarshaller();
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        marshal.marshal(def, bos);
+
+        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+        Object clone = unmarshaller.unmarshal(bis);
+
+        if (clone != null && clone instanceof RouteDefinition) {
+            RouteDefinition def2 = (RouteDefinition) clone;
+
+            // need to clone the namespaces also as they are not JAXB marshalled (as they are transient)
+            Iterator<ExpressionNode> it = ProcessorDefinitionHelper.filterTypeInOutputs(def.getOutputs(), ExpressionNode.class);
+            Iterator<ExpressionNode> it2 = ProcessorDefinitionHelper.filterTypeInOutputs(def2.getOutputs(), ExpressionNode.class);
+            while (it.hasNext() && it2.hasNext()) {
+                ExpressionNode node = it.next();
+                ExpressionNode node2 = it2.next();
+
+                NamespaceAwareExpression name = null;
+                NamespaceAwareExpression name2 = null;
+                if (node.getExpression() instanceof NamespaceAwareExpression) {
+                    name = (NamespaceAwareExpression) node.getExpression();
+                }
+                if (node2.getExpression() instanceof NamespaceAwareExpression) {
+                    name2 = (NamespaceAwareExpression) node2.getExpression();
+                }
+
+                if (name != null && name2 != null && name.getNamespaces() != null && !name.getNamespaces().isEmpty()) {
+                    Map<String, String> map = new HashMap<String, String>();
+                    map.putAll(name.getNamespaces());
+                    name2.setNamespaces(map);
+                }
+            }
+
+            return def2;
+        }
+
+        return null;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/f85ca1d0/components/camel-spring/src/test/java/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.java
----------------------------------------------------------------------
diff --git a/components/camel-spring/src/test/java/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.java b/components/camel-spring/src/test/java/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.java
new file mode 100644
index 0000000..4d953cb
--- /dev/null
+++ b/components/camel-spring/src/test/java/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.java
@@ -0,0 +1,61 @@
+/**
+ * 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.spring.config;
+
+import junit.framework.TestCase;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.springframework.context.support.AbstractXmlApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * @version 
+ */
+public class RouteRefPropertyPlaceholderMultipleCamelContextRefsTest extends TestCase {
+
+    protected AbstractXmlApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.xml");
+    }
+
+    public void testSpringTwoCamelContextDirectEndpoint() throws Exception {
+        AbstractXmlApplicationContext ac = createApplicationContext();
+        ac.start();
+
+        CamelContext camel1 = ac.getBean("myCamel-1", CamelContext.class);
+        CamelContext camel2 = ac.getBean("myCamel-2", CamelContext.class);
+
+        Endpoint start1 = camel1.getEndpoint("direct:start");
+        Endpoint start2 = camel2.getEndpoint("direct:start");
+        assertNotSame(start1, start2);
+        
+        MockEndpoint mock1 = camel1.getEndpoint("mock:end-1", MockEndpoint.class);
+        mock1.expectedBodiesReceived("Hello World");
+
+        MockEndpoint mock2 = camel2.getEndpoint("mock:end-2", MockEndpoint.class);
+        mock2.expectedBodiesReceived("Bye World");
+
+        camel1.createProducerTemplate().sendBody("direct:start", "Hello World");
+        camel2.createProducerTemplate().sendBody("direct:start", "Bye World");
+
+        mock1.assertIsSatisfied();
+        mock2.assertIsSatisfied();
+
+        ac.stop();
+    }
+    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/f85ca1d0/components/camel-spring/src/test/resources/mycamel-1.properties
----------------------------------------------------------------------
diff --git a/components/camel-spring/src/test/resources/mycamel-1.properties b/components/camel-spring/src/test/resources/mycamel-1.properties
new file mode 100644
index 0000000..508e0dc
--- /dev/null
+++ b/components/camel-spring/src/test/resources/mycamel-1.properties
@@ -0,0 +1,18 @@
+## ------------------------------------------------------------------------
+## 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.
+## ------------------------------------------------------------------------
+
+end=mock:end-1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/f85ca1d0/components/camel-spring/src/test/resources/mycamel-2.properties
----------------------------------------------------------------------
diff --git a/components/camel-spring/src/test/resources/mycamel-2.properties b/components/camel-spring/src/test/resources/mycamel-2.properties
new file mode 100644
index 0000000..34fecb9
--- /dev/null
+++ b/components/camel-spring/src/test/resources/mycamel-2.properties
@@ -0,0 +1,18 @@
+## ------------------------------------------------------------------------
+## 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.
+## ------------------------------------------------------------------------
+
+end=mock:end-2
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/f85ca1d0/components/camel-spring/src/test/resources/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.xml
----------------------------------------------------------------------
diff --git a/components/camel-spring/src/test/resources/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.xml b/components/camel-spring/src/test/resources/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.xml
new file mode 100644
index 0000000..b690aa6
--- /dev/null
+++ b/components/camel-spring/src/test/resources/org/apache/camel/spring/config/RouteRefPropertyPlaceholderMultipleCamelContextRefsTest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+
+  <routeContext id="myCoolRoute" xmlns="http://camel.apache.org/schema/spring">
+    <route id="cool">
+      <from uri="direct:start"/>
+      <to uri="{{end}}"/>
+    </route>
+  </routeContext>
+
+  <camelContext id="myCamel-1" xmlns="http://camel.apache.org/schema/spring">
+    <propertyPlaceholder id="properties1" location="mycamel-1.properties"/>
+    <routeContextRef ref="myCoolRoute"/>
+  </camelContext>
+
+  <camelContext id="myCamel-2" xmlns="http://camel.apache.org/schema/spring">
+    <propertyPlaceholder id="properties2" location="mycamel-2.properties"/>
+    <routeContextRef ref="myCoolRoute"/>
+  </camelContext>
+
+</beans>