This is an automated email from the ASF dual-hosted git repository. nfilotto pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-karaf.git
The following commit(s) were added to refs/heads/main by this push: new 4c0142e0 Ref #339: jcache fixes and integration test (#340) 4c0142e0 is described below commit 4c0142e0cf4c95bef50aae721bbdbd1ed87fdcf1 Author: François de Parscau <116000379+f2p...@users.noreply.github.com> AuthorDate: Thu Jun 13 16:18:40 2024 +0200 Ref #339: jcache fixes and integration test (#340) --- components/camel-hazelcast/pom.xml | 4 + components/camel-jcache/pom.xml | 28 +++++ .../camel/component/jcache/osgi/Activator.java | 41 ++++++++ .../component/jcache/osgi/OSGiCacheManager.java | 116 +++++++++++++++++++++ .../jcache/osgi/OSGiCacheManagerFactory.java | 31 ++++++ tests/features/camel-jcache/pom.xml | 47 +++++++++ .../test/AbstractCamelJcacheRouteSupplier.java | 51 +++++++++ .../camel/test/CamelJcacheEhRouteSupplier.java | 35 +++++++ .../camel/test/CamelJcacheHzRouteSupplier.java | 43 ++++++++ .../karaf/camel/itest/CamelJcacheEhITest.java | 49 +++++++++ .../karaf/camel/itest/CamelJcacheHzITest.java | 49 +++++++++ tests/features/pom.xml | 1 + 12 files changed, 495 insertions(+) diff --git a/components/camel-hazelcast/pom.xml b/components/camel-hazelcast/pom.xml index c16b9328..c5669c06 100644 --- a/components/camel-hazelcast/pom.xml +++ b/components/camel-hazelcast/pom.xml @@ -37,6 +37,10 @@ org.apache.camel*;version=${camel.version} </camel.osgi.export> <camel.osgi.import> + javax.cache;resolution:=optional, + javax.cache.integration;resolution:=optional, + javax.cache.configuration;resolution:=optional, + javax.cache.processor;resolution:=optional, * </camel.osgi.import> </properties> diff --git a/components/camel-jcache/pom.xml b/components/camel-jcache/pom.xml index 2499a2e4..3771dd89 100644 --- a/components/camel-jcache/pom.xml +++ b/components/camel-jcache/pom.xml @@ -34,11 +34,13 @@ <properties> <camel.osgi.export> + !org.apache.camel.util*, org.apache.camel*;version=${camel.version} </camel.osgi.export> <camel.osgi.import> * </camel.osgi.import> + <camel.osgi.activator>org.apache.camel.component.jcache.osgi.Activator</camel.osgi.activator> </properties> <dependencies> @@ -53,10 +55,36 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-util</artifactId> + <version>${camel.version}</version> + <scope>provided</scope> + </dependency> + <!-- osgi support --> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>osgi.core</artifactId> + <scope>provided</scope> + <optional>true</optional> + </dependency> </dependencies> <build> <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <executions> + <execution> + <id>recompile</id> + <phase>process-classes</phase> + <goals> + <goal>compile</goal> + </goals> + </execution> + </executions> + </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> diff --git a/components/camel-jcache/src/main/java/org/apache/camel/component/jcache/osgi/Activator.java b/components/camel-jcache/src/main/java/org/apache/camel/component/jcache/osgi/Activator.java new file mode 100644 index 00000000..9bf3efb2 --- /dev/null +++ b/components/camel-jcache/src/main/java/org/apache/camel/component/jcache/osgi/Activator.java @@ -0,0 +1,41 @@ +/* + * 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.component.jcache.osgi; + +import org.apache.camel.component.jcache.JCacheManagerFactory; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + +public class Activator implements BundleActivator { + private ServiceRegistration<?> registration; + + @Override + public void start(BundleContext context) throws Exception { + Object factory = new OSGiCacheManagerFactory(); + registration = context.registerService(JCacheManagerFactory.class.getName(), factory, null); + } + + @Override + public void stop(BundleContext context) throws Exception { + // release the reference + if (registration != null) { + registration.unregister(); + } + } + +} \ No newline at end of file diff --git a/components/camel-jcache/src/main/java/org/apache/camel/component/jcache/osgi/OSGiCacheManager.java b/components/camel-jcache/src/main/java/org/apache/camel/component/jcache/osgi/OSGiCacheManager.java new file mode 100644 index 00000000..54e6a2a1 --- /dev/null +++ b/components/camel-jcache/src/main/java/org/apache/camel/component/jcache/osgi/OSGiCacheManager.java @@ -0,0 +1,116 @@ +/* + * 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.component.jcache.osgi; + +import org.apache.camel.component.jcache.JCacheConfiguration; +import org.apache.camel.component.jcache.JCacheHelper; +import org.apache.camel.component.jcache.JCacheManager; +import org.apache.camel.component.jcache.JCacheProvider; +import org.apache.camel.component.jcache.JCacheProviders; +import org.apache.camel.util.ObjectHelper; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.wiring.BundleWiring; + +import javax.cache.Cache; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.Enumeration; + +public final class OSGiCacheManager<K, V> extends JCacheManager { + public OSGiCacheManager(JCacheConfiguration configuration) { + super(configuration); + } + + @Override + public synchronized Cache<K, V> doGetCache(JCacheProvider provider) throws Exception { + final ClassLoader jcl = getClassLoader(provider.className()); + final ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + + try { + if (jcl != null) { + Thread.currentThread().setContextClassLoader(jcl); + } + + Cache<K, V> cache = super.doGetCache(provider); + if (provider == JCacheProviders.hazelcast && jcl != null) { + cache = JCacheHelper.tcclProxy(cache, Cache.class, jcl); + } + + return cache; + } finally { + Thread.currentThread().setContextClassLoader(tccl); + } + } + + private ClassLoader getClassLoader(String providerName) throws Exception { + if (providerName == null || !getConfiguration().isLookupProviders()) { + return null; + } + + final BundleContext bc = FrameworkUtil.getBundle(JCacheHelper.class).getBundleContext(); + final ClassLoader bcl = bc.getBundle().adapt(BundleWiring.class).getClassLoader(); + final ClassLoader acl = getConfiguration().getApplicationContextClassLoader(); + + for (final Bundle bundle : bc.getBundles()) { + URL spi = bundle.getResource("META-INF/services/javax.cache.spi.CachingProvider"); + if (spi != null) { + try (BufferedReader in = new BufferedReader(new InputStreamReader(spi.openStream()))) { + String currentLine; + while( (currentLine = in.readLine()) != null) { + if (ObjectHelper.equal(providerName, currentLine)) { + return new ClassLoader(bcl) { + + @Override + protected Class<?> findClass(String name) throws ClassNotFoundException { + try { + return acl.loadClass(name); + } catch (ClassNotFoundException e) { + return bundle.loadClass(name); + } + } + + @Override + protected URL findResource(String name) { + URL resource = acl.getResource(name); + if (resource == null) { + resource = bundle.getResource(name); + } + return resource; + } + + @Override + protected Enumeration findResources(String name) throws IOException { + try { + return acl.getResources(name); + } catch (IOException e) { + return bundle.getResources(name); + } + } + }; + } + } + } + } + } + + return null; + } +} \ No newline at end of file diff --git a/components/camel-jcache/src/main/java/org/apache/camel/component/jcache/osgi/OSGiCacheManagerFactory.java b/components/camel-jcache/src/main/java/org/apache/camel/component/jcache/osgi/OSGiCacheManagerFactory.java new file mode 100644 index 00000000..2a4c30af --- /dev/null +++ b/components/camel-jcache/src/main/java/org/apache/camel/component/jcache/osgi/OSGiCacheManagerFactory.java @@ -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.component.jcache.osgi; + +import org.apache.camel.component.jcache.JCacheConfiguration; +import org.apache.camel.component.jcache.JCacheManager; +import org.apache.camel.component.jcache.JCacheManagerFactory; + +public class OSGiCacheManagerFactory implements JCacheManagerFactory { + + @Override + @SuppressWarnings("unchecked") + public <K, V> JCacheManager<K, V> createManager(JCacheConfiguration configuration) { + return new OSGiCacheManager<>(configuration); + } + +} \ No newline at end of file diff --git a/tests/features/camel-jcache/pom.xml b/tests/features/camel-jcache/pom.xml new file mode 100644 index 00000000..7b329995 --- /dev/null +++ b/tests/features/camel-jcache/pom.xml @@ -0,0 +1,47 @@ +<?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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.camel.karaf</groupId> + <artifactId>camel-karaf-features-test</artifactId> + <version>4.6.0-SNAPSHOT</version> + </parent> + + <artifactId>camel-jcache-test</artifactId> + <name>Apache Camel :: Karaf :: Tests :: Features :: JCache</name> + + <dependencies> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-jcache</artifactId> + <version>${camel.version}</version> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-hazelcast</artifactId> + <version>${camel.version}</version> + <optional>true</optional> + </dependency> + </dependencies> + +</project> \ No newline at end of file diff --git a/tests/features/camel-jcache/src/main/java/org/apache/karaf/camel/test/AbstractCamelJcacheRouteSupplier.java b/tests/features/camel-jcache/src/main/java/org/apache/karaf/camel/test/AbstractCamelJcacheRouteSupplier.java new file mode 100644 index 00000000..0c59359c --- /dev/null +++ b/tests/features/camel-jcache/src/main/java/org/apache/karaf/camel/test/AbstractCamelJcacheRouteSupplier.java @@ -0,0 +1,51 @@ +/* + * 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.karaf.camel.test; + +import java.util.function.Function; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.jcache.JCacheConstants; +import org.apache.camel.model.RouteDefinition; +import org.apache.karaf.camel.itests.AbstractCamelSingleFeatureResultMockBasedRouteSupplier; +import org.apache.karaf.camel.itests.CamelRouteSupplier; +import org.osgi.service.component.annotations.Component; + + +public abstract class AbstractCamelJcacheRouteSupplier extends AbstractCamelSingleFeatureResultMockBasedRouteSupplier { + + public static final String TEST_CACHE_NAME = "mycache"; + + protected abstract String getProvider(); + + @Override + protected Function<RouteBuilder, RouteDefinition> consumerRoute() { + return builder -> + builder.fromF("jcache://%s?cachingProvider=%s&lookupProviders=true", TEST_CACHE_NAME, getProvider()) + .log("received message ${body}"); + } + + @Override + protected void configureProducer(RouteBuilder builder, RouteDefinition producerRoute) { + producerRoute.log("Storing in cache") + .setBody(builder.constant("OK")) + .setHeader(JCacheConstants.ACTION).constant("PUT") + .setHeader(JCacheConstants.KEY).constant("OK") + .toF("jcache://%s?cachingProvider=%s&lookupProviders=true", TEST_CACHE_NAME, getProvider()) + .log("Cached value: ${body}"); + } +} + diff --git a/tests/features/camel-jcache/src/main/java/org/apache/karaf/camel/test/CamelJcacheEhRouteSupplier.java b/tests/features/camel-jcache/src/main/java/org/apache/karaf/camel/test/CamelJcacheEhRouteSupplier.java new file mode 100644 index 00000000..88421e6f --- /dev/null +++ b/tests/features/camel-jcache/src/main/java/org/apache/karaf/camel/test/CamelJcacheEhRouteSupplier.java @@ -0,0 +1,35 @@ +/* + * 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.karaf.camel.test; + +import org.apache.karaf.camel.itests.CamelRouteSupplier; +import org.osgi.service.component.annotations.Component; + +@Component( + name = "karaf-camel-jcache-eh-test", + immediate = true, + service = CamelRouteSupplier.class +) +public class CamelJcacheEhRouteSupplier extends AbstractCamelJcacheRouteSupplier { + + public static final String PROVIDER_CLASS = "org.ehcache.jsr107.EhcacheCachingProvider"; + + @Override + protected String getProvider() { + return PROVIDER_CLASS; + } +} + diff --git a/tests/features/camel-jcache/src/main/java/org/apache/karaf/camel/test/CamelJcacheHzRouteSupplier.java b/tests/features/camel-jcache/src/main/java/org/apache/karaf/camel/test/CamelJcacheHzRouteSupplier.java new file mode 100644 index 00000000..8b20b069 --- /dev/null +++ b/tests/features/camel-jcache/src/main/java/org/apache/karaf/camel/test/CamelJcacheHzRouteSupplier.java @@ -0,0 +1,43 @@ +/* + * 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.karaf.camel.test; + +import org.apache.camel.CamelContext; +import org.apache.karaf.camel.itests.CamelRouteSupplier; +import org.osgi.service.component.annotations.Component; + +import com.hazelcast.spi.properties.ClusterProperty; + +@Component( + name = "karaf-camel-jcache-hz-test", + immediate = true, + service = CamelRouteSupplier.class +) +public class CamelJcacheHzRouteSupplier extends AbstractCamelJcacheRouteSupplier { + + public static final String PROVIDER_CLASS = "com.hazelcast.cache.HazelcastCachingProvider"; + + @Override + public void configure(CamelContext camelContext) { + ClusterProperty.JCACHE_PROVIDER_TYPE.setSystemProperty("member"); + } + + @Override + protected String getProvider() { + return PROVIDER_CLASS; + } +} + diff --git a/tests/features/camel-jcache/src/test/java/org/apache/karaf/camel/itest/CamelJcacheEhITest.java b/tests/features/camel-jcache/src/test/java/org/apache/karaf/camel/itest/CamelJcacheEhITest.java new file mode 100644 index 00000000..ccadf856 --- /dev/null +++ b/tests/features/camel-jcache/src/test/java/org/apache/karaf/camel/itest/CamelJcacheEhITest.java @@ -0,0 +1,49 @@ +/* + * Licensed 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.karaf.camel.itest; + +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.karaf.camel.itests.AbstractCamelSingleFeatureResultMockBasedRouteITest; +import org.apache.karaf.camel.itests.CamelKarafTestHint; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +@CamelKarafTestHint(additionalRequiredFeatures = "camel-ehcache", camelRouteSuppliers = "karaf-camel-jcache-eh-test") +public class CamelJcacheEhITest extends AbstractCamelSingleFeatureResultMockBasedRouteITest { + + @Override + public String getCamelFeatureName() { + return "camel-jcache"; + } + + @Override + public String getTestBundleName() { + return "camel-jcache-test"; + } + + @Override + public void configureMock(MockEndpoint mock) { + mock.expectedBodiesReceived("OK"); + } + + @Test + public void testResultMock() throws Exception { + assertMockEndpointsSatisfied(); + } +} \ No newline at end of file diff --git a/tests/features/camel-jcache/src/test/java/org/apache/karaf/camel/itest/CamelJcacheHzITest.java b/tests/features/camel-jcache/src/test/java/org/apache/karaf/camel/itest/CamelJcacheHzITest.java new file mode 100644 index 00000000..09179f5b --- /dev/null +++ b/tests/features/camel-jcache/src/test/java/org/apache/karaf/camel/itest/CamelJcacheHzITest.java @@ -0,0 +1,49 @@ +/* + * Licensed 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.karaf.camel.itest; + +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.karaf.camel.itests.AbstractCamelSingleFeatureResultMockBasedRouteITest; +import org.apache.karaf.camel.itests.CamelKarafTestHint; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +@CamelKarafTestHint(additionalRequiredFeatures = "camel-hazelcast", camelRouteSuppliers = "karaf-camel-jcache-hz-test") +public class CamelJcacheHzITest extends AbstractCamelSingleFeatureResultMockBasedRouteITest { + + @Override + public String getCamelFeatureName() { + return "camel-jcache"; + } + + @Override + public String getTestBundleName() { + return "camel-jcache-test"; + } + + @Override + public void configureMock(MockEndpoint mock) { + mock.expectedBodiesReceived("OK"); + } + + @Test + public void testResultMock() throws Exception { + assertMockEndpointsSatisfied(); + } +} \ No newline at end of file diff --git a/tests/features/pom.xml b/tests/features/pom.xml index 7cc28b0b..69f77369 100644 --- a/tests/features/pom.xml +++ b/tests/features/pom.xml @@ -46,6 +46,7 @@ <module>camel-ehcache</module> <module>camel-elasticsearch</module> <module>camel-hazelcast</module> + <module>camel-jcache</module> <module>camel-jetty</module> <module>camel-netty-http</module> <module>camel-mail</module>