camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ra...@apache.org
Subject svn commit: r1400729 - in /camel/trunk: components/camel-http/src/main/java/org/apache/camel/component/http/ components/camel-jetty/src/main/java/org/apache/camel/component/jetty/ tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/ ...
Date Sun, 21 Oct 2012 21:47:11 GMT
Author: raulk
Date: Sun Oct 21 21:47:11 2012
New Revision: 1400729

URL: http://svn.apache.org/viewvc?rev=1400729&view=rev
Log:
Fixed CAMEL-5722 Classloader mixup when consumers across bundles share the same camel-jetty
port

Added:
    camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/JettyClassloaderCheckProcessor.java
    camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/OSGiJettyCamelContextsClassloaderTest.java
    camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext1.xml
    camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext2.xml
Modified:
    camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/CamelServlet.java
    camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java

Modified: camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/CamelServlet.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/CamelServlet.java?rev=1400729&r1=1400728&r2=1400729&view=diff
==============================================================================
--- camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/CamelServlet.java
(original)
+++ camel/trunk/components/camel-http/src/main/java/org/apache/camel/component/http/CamelServlet.java
Sun Oct 21 21:47:11 2012
@@ -154,4 +154,43 @@ public class CamelServlet extends HttpSe
         this.servletName = servletName;
     }
     
+    /**
+     * Override the Thread Context ClassLoader if need be.
+     * @param exchange
+     * @return old classloader if overridden; otherwise returns null
+     */
+    protected ClassLoader overrideTccl(final Exchange exchange) {
+        ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
+        ClassLoader appCtxCl = exchange.getContext().getApplicationContextClassLoader();
+        if (oldClassLoader == null || appCtxCl == null) {
+            return null;
+        }
+        
+        if (!oldClassLoader.equals(appCtxCl)) {
+            Thread.currentThread().setContextClassLoader(appCtxCl);
+            if (log.isTraceEnabled()) {
+                log.trace("Overrode TCCL for exchangeId {} to {} on thread {}", 
+                        new Object[] {exchange.getExchangeId(), appCtxCl, Thread.currentThread().getName()});
+            }
+            return oldClassLoader;
+        }
+        return null;
+    }
+
+    /**
+     * Restore the Thread Context ClassLoader if the Old TCCL is not null.
+     * @param exchange
+     * @param oldTccl
+     */
+    protected void restoreTccl(final Exchange exchange, ClassLoader oldTccl) {
+        if (oldTccl == null) {
+            return;
+        }
+        Thread.currentThread().setContextClassLoader(oldTccl);
+        if (log.isTraceEnabled()) {
+            log.trace("Restored TCCL for exchangeId {} to {} on thread {}", 
+                    new String[] {exchange.getExchangeId(), oldTccl.toString(), Thread.currentThread().getName()});
+        }
+    }
+    
 }

Modified: camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java?rev=1400729&r1=1400728&r2=1400729&view=diff
==============================================================================
--- camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java
(original)
+++ camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java
Sun Oct 21 21:47:11 2012
@@ -115,8 +115,11 @@ public class CamelContinuationServlet ex
             // must suspend before we process the exchange
             continuation.suspend();
 
+            ClassLoader oldTccl = overrideTccl(exchange);
+            
             log.trace("Processing request for exchangeId: {}", exchange.getExchangeId());
             // use the asynchronous API to process the exchange
+            
             consumer.getAsyncProcessor().process(exchange, new AsyncCallback() {
                 public void done(boolean doneSync) {
                     // check if the exchange id is already expired
@@ -132,6 +135,10 @@ public class CamelContinuationServlet ex
                 }
             });
 
+            if (oldTccl != null) {
+                restoreTccl(exchange, oldTccl);
+            }
+            
             // return to let Jetty continuation to work as it will resubmit and invoke the
service
             // method again when its resumed
             return;

Added: camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/JettyClassloaderCheckProcessor.java
URL: http://svn.apache.org/viewvc/camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/JettyClassloaderCheckProcessor.java?rev=1400729&view=auto
==============================================================================
--- camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/JettyClassloaderCheckProcessor.java
(added)
+++ camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/JettyClassloaderCheckProcessor.java
Sun Oct 21 21:47:11 2012
@@ -0,0 +1,31 @@
+/**
+ * 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.itest.osgi.jetty;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+
+public class JettyClassloaderCheckProcessor implements Processor {
+
+    public void process(Exchange exchange) throws Exception {
+        ClassLoader contextCl = exchange.getContext().getApplicationContextClassLoader();
+        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+        String classloaders = contextCl.equals(tccl) + " --- " + contextCl + " --- " + tccl;
+        exchange.getOut().setBody(classloaders);
+    }
+
+}

Added: camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/OSGiJettyCamelContextsClassloaderTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/OSGiJettyCamelContextsClassloaderTest.java?rev=1400729&view=auto
==============================================================================
--- camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/OSGiJettyCamelContextsClassloaderTest.java
(added)
+++ camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/OSGiJettyCamelContextsClassloaderTest.java
Sun Oct 21 21:47:11 2012
@@ -0,0 +1,88 @@
+/**
+ * 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.itest.osgi.jetty;
+
+import org.apache.camel.itest.osgi.OSGiIntegrationTestSupport;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.ops4j.pax.swissbox.tinybundles.dp.Constants;
+
+import static org.ops4j.pax.exam.CoreOptions.provision;
+import static org.ops4j.pax.exam.OptionUtils.combine;
+import static org.ops4j.pax.swissbox.tinybundles.core.TinyBundles.newBundle;
+
+/**
+ * CAMEL-5722: Test to verify that routes sitting in different bundles but listening on the
same Jetty port,
+ * and thus, sharing the same container-wide Jetty Connector, do not share the classloader.
The TCCL should
+ * be different in each case, as for each route it should be the Classloader of their containing
bundle.
+ */
+@RunWith(JUnit4TestRunner.class)
+public class OSGiJettyCamelContextsClassloaderTest extends OSGiIntegrationTestSupport {
+    
+    @Test
+    public void testClassloadersAreCongruent() throws Exception {
+        // Wait a while to let all the service started
+        Thread.sleep(3000);
+        // test context 1
+        String endpointURI1 = "http://localhost:9010/camel-context-1/";
+        String response1 = template.requestBody(endpointURI1, "Hello World", String.class);
+        System.out.println("Response from Context 1: " + response1);
+        assertEquals("Camel Context 1 classloaders unequal", "true", response1.split(" ---
")[0]);
+        
+        // test context 2
+        String endpointURI2 = "http://localhost:9010/camel-context-2/";
+        String response2 = template.requestBody(endpointURI2, "Hello World", String.class);
+        System.out.println("Response from Context 2: " + response2);
+        assertEquals("Camel Context 2 classloaders unequal", "true", response2.split(" ---
")[0]);
+        
+        // contexts's both classloaders toString() representation must contain the bundle
symbolic ID
+        // definition of "both classloaders": the Camel Context classloader and the Thread
classloader during processing
+        assertTrue(response1.matches(".*CamelContextBundle1.*CamelContextBundle1.*"));
+        assertTrue(response2.matches(".*CamelContextBundle2.*CamelContextBundle2.*"));
+        
+    }
+    
+    @Configuration
+    public static Option[] configure() {
+        Option[] options = combine(
+            getDefaultCamelKarafOptions(),
+            // using the features to install the other camel components             
+            loadCamelFeatures("camel-jetty"),
+            //set up the camel context bundle1          
+            provision(newBundle().add("META-INF/spring/Classloader-CamelContext1.xml", OSGiJettyCamelContextsClassloaderTest.class.getResource("Classloader-CamelContext1.xml"))
+                      .add(JettyClassloaderCheckProcessor.class)
+                      .set(Constants.BUNDLE_SYMBOLICNAME, "org.apache.camel.itest.osgi.CamelContextBundle1")
+                      .set(Constants.BUNDLE_NAME, "CamelContext1")
+                      .set(Constants.DYNAMICIMPORT_PACKAGE, "*")
+                      .build()),
+                  
+            //set up the camel context bundle1          
+            provision(newBundle().add("META-INF/spring/Classloader-CamelContext2.xml", OSGiJettyCamelContextsClassloaderTest.class.getResource("Classloader-CamelContext2.xml"))
+                      .add(JettyClassloaderCheckProcessor.class)
+                      .set(Constants.BUNDLE_SYMBOLICNAME, "org.apache.camel.itest.osgi.CamelContextBundle2")
+                      .set(Constants.BUNDLE_NAME, "CamelContext2")
+                      .set(Constants.DYNAMICIMPORT_PACKAGE, "*")
+                      .build()));
+        
+        return options;
+    }
+    
+
+}

Added: camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext1.xml
URL: http://svn.apache.org/viewvc/camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext1.xml?rev=1400729&view=auto
==============================================================================
--- camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext1.xml
(added)
+++ camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext1.xml
Sun Oct 21 21:47:11 2012
@@ -0,0 +1,35 @@
+<?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"
+       xmlns:camel="http://camel.apache.org/schema/spring"
+       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">
+  
+  <bean id="jettyProcessor" class="org.apache.camel.itest.osgi.jetty.JettyClassloaderCheckProcessor"
/>
+
+  <camelContext id="camelContext1" xmlns="http://camel.apache.org/schema/spring">
+    <camel:route>
+      <camel:from uri="jetty:http://0.0.0.0:9010/camel-context-1/"/>
+      <camel:process ref="jettyProcessor"/>
+    </camel:route>
+  </camelContext>
+
+</beans>

Added: camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext2.xml
URL: http://svn.apache.org/viewvc/camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext2.xml?rev=1400729&view=auto
==============================================================================
--- camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext2.xml
(added)
+++ camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext2.xml
Sun Oct 21 21:47:11 2012
@@ -0,0 +1,35 @@
+<?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"
+       xmlns:camel="http://camel.apache.org/schema/spring"
+       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">
+  
+  <bean id="jettyProcessor" class="org.apache.camel.itest.osgi.jetty.JettyClassloaderCheckProcessor"
/>
+
+  <camelContext id="camelContext2" xmlns="http://camel.apache.org/schema/spring">
+    <camel:route>
+      <camel:from uri="jetty:http://0.0.0.0:9010/camel-context-2/"/>
+      <camel:process ref="jettyProcessor"/>
+    </camel:route>
+  </camelContext>
+
+</beans>



Mime
View raw message