Author: raulk
Date: Sat Oct 27 18:20:13 2012
New Revision: 1402833

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

Added:
    
camel/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/JettyClassloaderCheckProcessor.java
      - copied unchanged from r1400729, 
camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/JettyClassloaderCheckProcessor.java
    
camel/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/OSGiJettyCamelContextsClassloaderTest.java
      - copied, changed from r1400729, 
camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/OSGiJettyCamelContextsClassloaderTest.java
    
camel/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext1.xml
      - copied, changed from r1400729, 
camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext1.xml
    
camel/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext2.xml
      - copied, changed from r1400729, 
camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext2.xml
Modified:
    camel/branches/camel-2.9.x/   (props changed)
    
camel/branches/camel-2.9.x/components/camel-http/src/main/java/org/apache/camel/component/http/CamelServlet.java
    
camel/branches/camel-2.9.x/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java

Propchange: camel/branches/camel-2.9.x/
------------------------------------------------------------------------------
  Merged /camel/trunk:r1400729,1400734

Modified: 
camel/branches/camel-2.9.x/components/camel-http/src/main/java/org/apache/camel/component/http/CamelServlet.java
URL: 
http://svn.apache.org/viewvc/camel/branches/camel-2.9.x/components/camel-http/src/main/java/org/apache/camel/component/http/CamelServlet.java?rev=1402833&r1=1402832&r2=1402833&view=diff
==============================================================================
--- 
camel/branches/camel-2.9.x/components/camel-http/src/main/java/org/apache/camel/component/http/CamelServlet.java
 (original)
+++ 
camel/branches/camel-2.9.x/components/camel-http/src/main/java/org/apache/camel/component/http/CamelServlet.java
 Sat Oct 27 18:20:13 2012
@@ -85,6 +85,9 @@ public class CamelServlet extends HttpSe
             exchange.setProperty(Exchange.DISABLE_HTTP_STREAM_CACHE, 
Boolean.TRUE);
         }
 
+        // we override the classloader before building the HttpMessage just in 
case the binding
+        // does some class resolution
+        ClassLoader oldTccl = overrideTccl(exchange);
         HttpHelper.setCharsetFromContentType(request.getContentType(), 
exchange);
         exchange.setIn(new HttpMessage(exchange, request, response));
 
@@ -107,6 +110,8 @@ public class CamelServlet extends HttpSe
         } catch (Exception e) {
             log.error("Error processing request", e);
             throw new ServletException(e);
+        } finally {
+            restoreTccl(exchange, oldTccl);
         }
     }
 
@@ -146,4 +151,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/branches/camel-2.9.x/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java
URL: 
http://svn.apache.org/viewvc/camel/branches/camel-2.9.x/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java?rev=1402833&r1=1402832&r2=1402833&view=diff
==============================================================================
--- 
camel/branches/camel-2.9.x/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java
 (original)
+++ 
camel/branches/camel-2.9.x/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java
 Sat Oct 27 18:20:13 2012
@@ -108,8 +108,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
@@ -125,6 +128,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;

Copied: 
camel/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/OSGiJettyCamelContextsClassloaderTest.java
 (from r1400729, 
camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/OSGiJettyCamelContextsClassloaderTest.java)
URL: 
http://svn.apache.org/viewvc/camel/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/OSGiJettyCamelContextsClassloaderTest.java?p2=camel/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/OSGiJettyCamelContextsClassloaderTest.java&p1=camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/OSGiJettyCamelContextsClassloaderTest.java&r1=1400729&r2=1402833&rev=1402833&view=diff
==============================================================================
--- 
camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/OSGiJettyCamelContextsClassloaderTest.java
 (original)
+++ 
camel/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/jetty/OSGiJettyCamelContextsClassloaderTest.java
 Sat Oct 27 18:20:13 2012
@@ -26,6 +26,7 @@ import org.ops4j.pax.swissbox.tinybundle
 
 import static org.ops4j.pax.exam.CoreOptions.provision;
 import static org.ops4j.pax.exam.OptionUtils.combine;
+import static org.ops4j.pax.exam.container.def.PaxRunnerOptions.scanFeatures;
 import static org.ops4j.pax.swissbox.tinybundles.core.TinyBundles.newBundle;
 
 /**
@@ -41,13 +42,13 @@ public class OSGiJettyCamelContextsClass
         // Wait a while to let all the service started
         Thread.sleep(3000);
         // test context 1
-        String endpointURI1 = "http://localhost:9010/camel-context-1/";;
+        String endpointURI1 = 
"http://localhost:9010/camel-context-1/continuation/";;
         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 endpointURI2 = 
"http://localhost:9010/camel-context-2/continuation/";;
         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]);
@@ -57,6 +58,25 @@ public class OSGiJettyCamelContextsClass
         
assertTrue(response1.matches(".*CamelContextBundle1.*CamelContextBundle1.*"));
         
assertTrue(response2.matches(".*CamelContextBundle2.*CamelContextBundle2.*"));
         
+        // Wait a while to let all the service started
+        Thread.sleep(3000);
+        // test context 1
+        endpointURI1 = "http://localhost:9010/camel-context-1/noContinuation/";;
+        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
+        endpointURI2 = "http://localhost:9010/camel-context-2/noContinuation/";;
+        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
@@ -64,7 +84,7 @@ public class OSGiJettyCamelContextsClass
         Option[] options = combine(
             getDefaultCamelKarafOptions(),
             // using the features to install the other camel components        
     
-            loadCamelFeatures("camel-jetty"),
+            scanFeatures(getCamelKarafFeatureUrl(), "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)

Copied: 
camel/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext1.xml
 (from r1400729, 
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/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext1.xml?p2=camel/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext1.xml&p1=camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext1.xml&r1=1400729&r2=1402833&rev=1402833&view=diff
==============================================================================
--- 
camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext1.xml
 (original)
+++ 
camel/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext1.xml
 Sat Oct 27 18:20:13 2012
@@ -27,7 +27,12 @@
 
   <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:from 
uri="jetty:http://0.0.0.0:9010/camel-context-1/continuation/?useContinuation=true"/>
+      <camel:process ref="jettyProcessor"/>
+    </camel:route>
+    
+    <camel:route>
+      <camel:from 
uri="jetty:http://0.0.0.0:9010/camel-context-1/noContinuation/?useContinuation=false"/>
       <camel:process ref="jettyProcessor"/>
     </camel:route>
   </camelContext>

Copied: 
camel/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext2.xml
 (from r1400729, 
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/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext2.xml?p2=camel/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext2.xml&p1=camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext2.xml&r1=1400729&r2=1402833&rev=1402833&view=diff
==============================================================================
--- 
camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext2.xml
 (original)
+++ 
camel/branches/camel-2.9.x/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/jetty/Classloader-CamelContext2.xml
 Sat Oct 27 18:20:13 2012
@@ -27,7 +27,12 @@
 
   <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:from 
uri="jetty:http://0.0.0.0:9010/camel-context-2/continuation/?useContinuation=true"/>
+      <camel:process ref="jettyProcessor"/>
+    </camel:route>
+    
+    <camel:route>
+      <camel:from 
uri="jetty:http://0.0.0.0:9010/camel-context-2/noContinuation/?useContinuation=false"/>
       <camel:process ref="jettyProcessor"/>
     </camel:route>
   </camelContext>


Reply via email to