Author: gertv Date: Thu Aug 18 11:29:19 2011 New Revision: 1159171 URL: http://svn.apache.org/viewvc?rev=1159171&view=rev Log: CAMEL-4347: Set TCCL when starting camel-blueprint routes
Added: camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/CamelBlueprintTcclTest.java camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/blueprint/blueprint-tccl.xml Modified: camel/trunk/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/BlueprintCamelContext.java camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/utils/BundleDelegatingClassLoader.java Modified: camel/trunk/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/BlueprintCamelContext.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/BlueprintCamelContext.java?rev=1159171&r1=1159170&r2=1159171&view=diff ============================================================================== --- camel/trunk/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/BlueprintCamelContext.java (original) +++ camel/trunk/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/BlueprintCamelContext.java Thu Aug 18 11:29:19 2011 @@ -24,6 +24,7 @@ import org.apache.camel.core.osgi.OsgiFa import org.apache.camel.core.osgi.OsgiPackageScanClassResolver; import org.apache.camel.core.osgi.OsgiTypeConverter; import org.apache.camel.core.osgi.utils.BundleContextUtils; +import org.apache.camel.core.osgi.utils.BundleDelegatingClassLoader; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.spi.FactoryFinder; import org.apache.camel.spi.Registry; @@ -52,6 +53,7 @@ public class BlueprintCamelContext exten setComponentResolver(new BlueprintComponentResolver(bundleContext)); setLanguageResolver(new BlueprintLanguageResolver(bundleContext)); setDataFormatResolver(new BlueprintDataFormatResolver(bundleContext)); + setApplicationContextClassLoader(new BundleDelegatingClassLoader(bundleContext.getBundle())); } public BundleContext getBundleContext() { @@ -71,7 +73,14 @@ public class BlueprintCamelContext exten } public void init() throws Exception { - maybeStart(); + final ClassLoader original = Thread.currentThread().getContextClassLoader(); + try { + // let's set a more suitable TCCL while starting the context + Thread.currentThread().setContextClassLoader(getApplicationContextClassLoader()); + maybeStart(); + } finally { + Thread.currentThread().setContextClassLoader(original); + } } private void maybeStart() throws Exception { Modified: camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/utils/BundleDelegatingClassLoader.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/utils/BundleDelegatingClassLoader.java?rev=1159171&r1=1159170&r2=1159171&view=diff ============================================================================== --- camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/utils/BundleDelegatingClassLoader.java (original) +++ camel/trunk/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/utils/BundleDelegatingClassLoader.java Thu Aug 18 11:29:19 2011 @@ -87,4 +87,9 @@ public class BundleDelegatingClassLoader public Bundle getBundle() { return bundle; } + + @Override + public String toString() { + return String.format("BundleDelegatingClassLoader(%s)", bundle); + } } Added: camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/CamelBlueprintTcclTest.java URL: http://svn.apache.org/viewvc/camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/CamelBlueprintTcclTest.java?rev=1159171&view=auto ============================================================================== --- camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/CamelBlueprintTcclTest.java (added) +++ camel/trunk/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/osgi/blueprint/CamelBlueprintTcclTest.java Thu Aug 18 11:29:19 2011 @@ -0,0 +1,126 @@ +/** + * 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.blueprint; + +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.karaf.testing.Helper; +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.osgi.framework.Bundle; +import org.osgi.framework.Constants; +import org.osgi.service.blueprint.container.BlueprintContainer; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import static org.ops4j.pax.exam.CoreOptions.equinox; +import static org.ops4j.pax.exam.CoreOptions.felix; +import static org.ops4j.pax.exam.OptionUtils.combine; +import static org.ops4j.pax.exam.container.def.PaxRunnerOptions.scanFeatures; +import static org.ops4j.pax.exam.container.def.PaxRunnerOptions.workingDirectory; +import static org.ops4j.pax.swissbox.tinybundles.core.TinyBundles.newBundle; + +/** + * Test cases to ensure that the Blueprint component is correctly setting the Thread's context classloader when starting + * the routes + * + * @version + */ +@RunWith(JUnit4TestRunner.class) +public class CamelBlueprintTcclTest extends OSGiBlueprintTestSupport { + + private static final String BUNDLE_SYMBOLICNAME = "CamelBlueprintTcclTestBundle"; + + @Test + public void testCorrectTcclSetForRoutes() throws Exception { + BlueprintContainer ctn = getOsgiService(BlueprintContainer.class, "(osgi.blueprint.container.symbolicname=CamelBlueprintTcclTestBundle)", 10000); + CamelContext ctx = getOsgiService(CamelContext.class, "(camel.context.symbolicname=CamelBlueprintTcclTestBundle)", 10000); + assertBundleDelegatingClassLoader(ctx.getApplicationContextClassLoader()); + + ProducerTemplate template = ctx.createProducerTemplate(); + + MockEndpoint mock = ctx.getEndpoint("mock:result", MockEndpoint.class); + mock.expectedMessageCount(1); + + template.sendBody("direct:start", "<hello>world!</hello>"); + + mock.assertIsSatisfied(); + + ClassLoader tccl = mock.getExchanges().get(0).getProperty(ThreadContextClassLoaderBean.THREAD_CONTEXT_CLASS_LOADER, ClassLoader.class); + assertNotNull("Exchange property containing TCCL should have been set", tccl); + assertBundleDelegatingClassLoader(tccl); + + template.stop(); + } + + private void assertBundleDelegatingClassLoader(ClassLoader tccl) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + // camel-blueprint does not export the BundleDelegatingClassLoader package so we need a little pinch of reflection here + assertTrue("Expected a BundleDelegatingClassLoader instance", tccl.getClass().getName().contains("BundleDelegatingClassLoader")); + Method getBundle = tccl.getClass().getMethod("getBundle"); + Bundle bundle = (Bundle) getBundle.invoke(tccl); + + assertEquals(BUNDLE_SYMBOLICNAME, bundle.getSymbolicName()); + } + + @Configuration + public static Option[] configure() throws Exception { + return combine( + getDefaultCamelKarafOptions(), + + bundle(newBundle() + .add("OSGI-INF/blueprint/test.xml", OSGiBlueprintTestSupport.class.getResource("blueprint-tccl.xml")) + .add(ThreadContextClassLoaderBean.class) + .set(Constants.BUNDLE_SYMBOLICNAME, BUNDLE_SYMBOLICNAME) + .set(Constants.IMPORT_PACKAGE, "org.apache.camel") + .build()), + + // using the features to install the camel components + scanFeatures(getCamelKarafFeatureUrl(), "camel-blueprint"), + + workingDirectory("target/paxrunner/"), + + felix(), + equinox()); + } + + /** + * Camel {@link Processor} that injects startup thread context classloader into the exchange for testing purposes + */ + public static final class ThreadContextClassLoaderBean implements Processor { + + public static final String THREAD_CONTEXT_CLASS_LOADER = "CamelThreadContextClassLoader"; + + private final ClassLoader tccl; + + public ThreadContextClassLoaderBean() { + super(); + tccl = Thread.currentThread().getContextClassLoader(); + } + + @Override + public void process(Exchange exchange) throws Exception { + exchange.setProperty(THREAD_CONTEXT_CLASS_LOADER, tccl); + } + } +} Added: camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/blueprint/blueprint-tccl.xml URL: http://svn.apache.org/viewvc/camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/blueprint/blueprint-tccl.xml?rev=1159171&view=auto ============================================================================== --- camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/blueprint/blueprint-tccl.xml (added) +++ camel/trunk/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/osgi/blueprint/blueprint-tccl.xml Thu Aug 18 11:29:19 2011 @@ -0,0 +1,28 @@ +<?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. +--> +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> + + <camelContext xmlns="http://camel.apache.org/schema/blueprint"> + <route> + <from uri="direct:start"/> + <bean beanType="org.apache.camel.itest.osgi.blueprint.CamelBlueprintTcclTest$ThreadContextClassLoaderBean" /> + <to uri="mock:result"/> + </route> + </camelContext> + +</blueprint>