Repository: camel Updated Branches: refs/heads/master eef0e9d73 -> 9a473f398
CAMEL-9884 : Create a camel-ehcache component Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/9a473f39 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/9a473f39 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/9a473f39 Branch: refs/heads/master Commit: 9a473f3980f679b62a22fc6a191b54164ad38001 Parents: eef0e9d Author: lburgazzoli <lburgazz...@gmail.com> Authored: Tue May 10 15:12:12 2016 +0200 Committer: lburgazzoli <lburgazz...@gmail.com> Committed: Tue May 10 15:13:34 2016 +0200 ---------------------------------------------------------------------- apache-camel/pom.xml | 4 + .../src/main/descriptors/common-bin.xml | 1 + components/camel-ehcache/pom.xml | 83 +++++ .../component/ehcache/EhcacheComponent.java | 49 +++ .../component/ehcache/EhcacheConfiguration.java | 356 ++++++++++++++++++ .../component/ehcache/EhcacheConstants.java | 39 ++ .../component/ehcache/EhcacheConsumer.java | 75 ++++ .../component/ehcache/EhcacheEndpoint.java | 84 +++++ .../camel/component/ehcache/EhcacheManager.java | 99 +++++ .../component/ehcache/EhcacheProducer.java | 203 +++++++++++ .../src/main/resources/META-INF/LICENSE.txt | 203 +++++++++++ .../src/main/resources/META-INF/NOTICE.txt | 11 + .../services/org/apache/camel/component/ehcache | 1 + .../component/ehcache/EhcacheConsumerTest.java | 71 ++++ .../component/ehcache/EhcacheProducerTest.java | 361 +++++++++++++++++++ .../component/ehcache/EhcacheTestSupport.java | 105 ++++++ .../test/resources/ehcache/ehcache-config.xml | 34 ++ .../src/test/resources/log4j.properties | 21 ++ components/pom.xml | 1 + parent/pom.xml | 8 +- .../features/src/main/resources/features.xml | 5 + .../camel/itest/karaf/CamelEhcacheTest.java | 35 ++ 22 files changed, 1848 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/apache-camel/pom.xml ---------------------------------------------------------------------- diff --git a/apache-camel/pom.xml b/apache-camel/pom.xml index 95b808a..8f8c2f7 100644 --- a/apache-camel/pom.xml +++ b/apache-camel/pom.xml @@ -213,6 +213,10 @@ </dependency> <dependency> <groupId>org.apache.camel</groupId> + <artifactId>camel-ehcache</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> <artifactId>camel-ejb</artifactId> </dependency> <dependency> http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/apache-camel/src/main/descriptors/common-bin.xml ---------------------------------------------------------------------- diff --git a/apache-camel/src/main/descriptors/common-bin.xml b/apache-camel/src/main/descriptors/common-bin.xml index 34a34f1..ae84bf4 100644 --- a/apache-camel/src/main/descriptors/common-bin.xml +++ b/apache-camel/src/main/descriptors/common-bin.xml @@ -66,6 +66,7 @@ <include>org.apache.camel:camel-dozer</include> <include>org.apache.camel:camel-dropbox</include> <include>org.apache.camel:camel-eclipse</include> + <include>org.apache.camel:camel-ehcache</include> <include>org.apache.camel:camel-ejb</include> <include>org.apache.camel:camel-elasticsearch</include> <include>org.apache.camel:camel-elsql</include> http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/pom.xml ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/pom.xml b/components/camel-ehcache/pom.xml new file mode 100644 index 0000000..c9ec2ab --- /dev/null +++ b/components/camel-ehcache/pom.xml @@ -0,0 +1,83 @@ +<?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/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.camel</groupId> + <artifactId>components</artifactId> + <version>2.18-SNAPSHOT</version> + </parent> + + <artifactId>camel-ehcache</artifactId> + <packaging>jar</packaging> + <name>Camel : Ehcache</name> + <description>Camel Ehcache support</description> + + <properties> + <camel.osgi.export.pkg> + org.apache.camel.component.ehcache.*, + </camel.osgi.export.pkg> + <camel.osgi.export.service> + org.apache.camel.spi.ComponentResolver;component=ehcache + </camel.osgi.export.service> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-core</artifactId> + </dependency> + <dependency> + <groupId>org.ehcache</groupId> + <artifactId>ehcache</artifactId> + <version>${ehcache3-version}</version> + </dependency> + + <!-- testing --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <version>${mockito-version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>java-hamcrest</artifactId> + <version>${hamcrest-version}</version> + <scope>test</scope> + </dependency> + </dependencies> + +</project> http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheComponent.java b/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheComponent.java new file mode 100644 index 0000000..dd1e0a6 --- /dev/null +++ b/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheComponent.java @@ -0,0 +1,49 @@ +/** + * 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.ehcache; + +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.Endpoint; +import org.apache.camel.impl.UriEndpointComponent; + +/** + * Represents the component that manages {@link EhcacheEndpoint}. + */ +public class EhcacheComponent extends UriEndpointComponent { + + public EhcacheComponent() { + super(EhcacheEndpoint.class); + } + + public EhcacheComponent(CamelContext context) { + super(context, EhcacheEndpoint.class); + } + + @Override + protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { + return new EhcacheEndpoint( + uri, + this, + EhcacheConfiguration.create( + getCamelContext(), + remaining, + parameters) + ); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheConfiguration.java ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheConfiguration.java b/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheConfiguration.java new file mode 100644 index 0000000..a0bae81 --- /dev/null +++ b/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheConfiguration.java @@ -0,0 +1,356 @@ +/** + * 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.ehcache; + +import java.io.IOException; +import java.net.URL; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.camel.CamelContext; +import org.apache.camel.spi.UriParam; +import org.apache.camel.spi.UriParams; +import org.apache.camel.util.EndpointHelper; +import org.apache.camel.util.IntrospectionSupport; +import org.apache.camel.util.ResourceHelper; +import org.ehcache.CacheManager; +import org.ehcache.config.CacheConfiguration; +import org.ehcache.config.ResourcePools; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.event.EventFiring; +import org.ehcache.event.EventOrdering; +import org.ehcache.event.EventType; +import org.ehcache.xml.XmlConfiguration; + +@UriParams +public class EhcacheConfiguration { + public static final String PREFIX_CACHE = "cache."; + public static final String PREFIX_POOL = "pool."; + + private final CamelContext context; + private final String cacheName; + + @UriParam + private String configUri; + + @UriParam(defaultValue = "true") + private boolean createCacheIfNotExist = true; + + @UriParam(label = "producer") + private String action; + @UriParam(label = "producer") + private String key; + + @UriParam + private CacheManager cacheManager; + @UriParam(label = "advanced") + private CacheConfiguration<?, ?> defaultCacheConfiguration; + @UriParam(label = "advanced") + private ResourcePools defaultCacheResourcePools; + + @UriParam(label = "advanced", prefix = PREFIX_CACHE, multiValue = true, javaType = "java.lang.String") + private Map<String, CacheConfiguration> cacheConfigurations; + @UriParam(label = "advanced", prefix = PREFIX_POOL, multiValue = true, javaType = "java.lang.String") + private Map<String, ResourcePools> cacheResourcePools; + + @UriParam( + label = "consumer", + enums = "ORDERED,UNORDERED", + defaultValue = "ORDERED") + private EventOrdering eventOrdering = EventOrdering.ORDERED; + + @UriParam( + label = "consumer", + enums = "ASYNCHRONOUS, SYNCHRONOUS", + defaultValue = "ASYNCHRONOUS") + private EventFiring eventFiring = EventFiring.ASYNCHRONOUS; + + @UriParam( + label = "consumer", + enums = "EVICTED,EXPIRED,REMOVED,CREATED,UPDATED", + defaultValue = "EVICTED,EXPIRED,REMOVED,CREATED,UPDATED") + private Set<EventType> eventTypes = EnumSet.of(EventType.values()[0], EventType.values()); + + EhcacheConfiguration(String cacheName) { + this(null, cacheName); + } + + EhcacheConfiguration(CamelContext context, String cacheName) { + this.context = context; + this.cacheName = cacheName; + } + + public CamelContext getContext() { + return context; + } + + public String getCacheName() { + return cacheName; + } + + public String getConfigUri() { + return configUri; + } + + public URL getConfigUriAsUrl() throws IOException { + return context != null + ? ResourceHelper.resolveMandatoryResourceAsUrl(context.getClassResolver(), configUri) + : new URL(configUri); + } + + /** + * URI pointing to the Ehcache XML configuration file's location + */ + public void setConfigUri(String configUri) { + this.configUri = configUri; + } + + public boolean isCreateCacheIfNotExist() { + return createCacheIfNotExist; + } + + /** + * Configure if a cache need to be created if it does exist or can't be + * pre-configured. + */ + public void setCreateCacheIfNotExist(boolean createCacheIfNotExist) { + this.createCacheIfNotExist = createCacheIfNotExist; + } + + public String getAction() { + return action; + } + + /** + * To configure the default cache action. If an action is set in the message + * header, then the operation from the header takes precedence. + */ + public void setAction(String action) { + this.action = action; + } + + public String getKey() { + return key; + } + + /** + * To configure the default action key. If a key is set in the message + * header, then the key from the header takes precedence. + */ + public void setKey(String key) { + this.key = key; + } + + public CacheManager getCacheManager() { + return cacheManager; + } + + /** + * The cache manager + */ + public void setCacheManager(CacheManager cacheManager) { + this.cacheManager = cacheManager; + } + + public boolean hasCacheManager() { + return this.cacheManager != null; + } + + public EventOrdering getEventOrdering() { + return eventOrdering; + } + + /** + * Set the the delivery mode (ordered, unordered) + */ + public void setEventOrdering(String eventOrdering) { + setEventOrdering(EventOrdering.valueOf(eventOrdering)); + } + + public void setEventOrdering(EventOrdering eventOrdering) { + this.eventOrdering = eventOrdering; + } + + public EventFiring getEventFiring() { + return eventFiring; + } + + /** + * Set the the delivery mode (synchronous, asynchronous) + */ + public void setEventFiring(String eventFiring) { + setEventFiring(EventFiring.valueOf(eventFiring)); + } + + public void setEventFiring(EventFiring eventFiring) { + this.eventFiring = eventFiring; + } + + public Set<EventType> getEventTypes() { + return eventTypes; + } + + /** + * Set the type of events to listen for + */ + public void setEventTypes(String eventTypesString) { + Set<EventType> eventTypes = new HashSet<>(); + String[] events = eventTypesString.split(","); + for (String event : events) { + eventTypes.add(EventType.valueOf(event)); + } + + setEventTypes(eventTypes); + } + + public void setEventTypes(Set<EventType> eventTypes) { + this.eventTypes = new HashSet<>(eventTypes); + } + + // **************************** + // Cache Configuration + // **************************** + + /** + * The default cache configuration to be used to create caches. + */ + public void setDefaultCacheConfiguration(CacheConfiguration<?, ?> defaultCacheConfiguration) { + this.defaultCacheConfiguration = defaultCacheConfiguration; + } + + public CacheConfiguration<?, ?> getDefaultCacheConfiguration() { + return defaultCacheConfiguration; + } + + /** + * The cache configuration to be used for cache cacheName. + */ + public void addCacheConfiguration(String cacheName, CacheConfiguration cacheConfiguration) { + if (cacheConfigurations == null) { + cacheConfigurations = new HashMap<>(); + } + + cacheConfigurations.put(cacheName, cacheConfiguration); + } + + EhcacheConfiguration addCacheConfigurationFromParameters(Map<String, Object> parameters) { + Map<String, Object> models = IntrospectionSupport.extractProperties(parameters, PREFIX_CACHE); + for (Map.Entry<String, Object> entry : models.entrySet()) { + addCacheConfiguration( + entry.getKey(), + EndpointHelper.resolveParameter( + context, + (String)entry.getValue(), + CacheConfiguration.class + ) + ); + } + + return this; + } + + public CacheConfiguration getCacheConfiguration(String cacheName) { + return cacheConfigurations != null + ? cacheConfigurations.getOrDefault(cacheName, defaultCacheConfiguration) + : defaultCacheConfiguration; + } + + // **************************** + // Cache Resource Pools + // **************************** + + public ResourcePools getDefaultCacheResourcePools() { + return defaultCacheResourcePools; + } + + /** + * The default resource pools to be used to create caches. + */ + public void setDefaultCacheResourcePools(ResourcePools defaultCacheResourcePools) { + this.defaultCacheResourcePools = defaultCacheResourcePools; + } + + /** + * The resource pools to be used for cache cacheName. + */ + public void addResourcePools(String cacheName, ResourcePools resourcePools) { + if (cacheResourcePools == null) { + cacheResourcePools = new HashMap<>(); + } + + cacheResourcePools.put(cacheName, resourcePools); + } + + EhcacheConfiguration addResourcePoolsFromParameters(Map<String, Object> parameters) { + Map<String, Object> models = IntrospectionSupport.extractProperties(parameters, PREFIX_POOL); + for (Map.Entry<String, Object> entry : models.entrySet()) { + addResourcePools( + entry.getKey(), + EndpointHelper.resolveParameter( + context, + (String)entry.getValue(), + ResourcePools.class + ) + ); + } + + return this; + } + + public ResourcePools getResourcePools(String cacheName) { + return cacheResourcePools != null + ? cacheResourcePools.getOrDefault(cacheName, defaultCacheResourcePools) + : defaultCacheResourcePools; + } + + // **************************** + // Helpers + // **************************** + + static EhcacheConfiguration create(CamelContext context, String remaining, Map<String, Object> parameters) throws Exception { + EhcacheConfiguration configuration = new EhcacheConfiguration(context, remaining); + configuration.addCacheConfigurationFromParameters(parameters); + configuration.addResourcePoolsFromParameters(parameters); + + EndpointHelper.setReferenceProperties(context, configuration, parameters); + EndpointHelper.setProperties(context, configuration, parameters); + + return configuration; + } + + CacheManager createCacheManager() throws IOException { + CacheManager manager; + + if (cacheManager != null) { + manager = cacheManager; + } else if (configUri != null) { + manager = CacheManagerBuilder.newCacheManager(new XmlConfiguration(getConfigUriAsUrl())); + } else { + CacheManagerBuilder builder = CacheManagerBuilder.newCacheManagerBuilder(); + if (cacheConfigurations != null) { + cacheConfigurations.forEach(builder::withCache); + } + + manager = builder.build(); + } + + return manager; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheConstants.java ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheConstants.java b/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheConstants.java new file mode 100644 index 0000000..35ee739 --- /dev/null +++ b/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheConstants.java @@ -0,0 +1,39 @@ +/** + * 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.ehcache; + + +public interface EhcacheConstants { + String ACTION = "CamelEhcacheAction"; + String ACTION_HAS_RESULT = "CamelEhcacheActionHasResult"; + String ACTION_SUCCEEDED = "CamelEhcacheActionSucceeded"; + String KEY = "CamelEhcacheKey"; + String KEYS = "CamelEhcacheKeys"; + String VALUE = "CamelEhcacheValue"; + String OLD_VALUE = "CamelEhcacheOldValue"; + String EVENT_TYPE = "CamelEhcacheEventValue"; + + String ACTION_CLEAR = "CLEAR"; + String ACTION_PUT = "PUT"; + String ACTION_PUT_ALL = "PUT_ALL"; + String ACTION_PUT_IF_ABSENT = "PUT_IF_ABSENT"; + String ACTION_GET = "GET"; + String ACTION_GET_ALL = "GET_ALL"; + String ACTION_REMOVE = "REMOVE"; + String ACTION_REMOVE_ALL = "REMOVE_ALL"; + String ACTION_REPLACE = "REPLACE"; +} http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheConsumer.java ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheConsumer.java b/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheConsumer.java new file mode 100644 index 0000000..1129081 --- /dev/null +++ b/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheConsumer.java @@ -0,0 +1,75 @@ +/** + * 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.ehcache; + +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.Processor; +import org.apache.camel.impl.DefaultConsumer; +import org.ehcache.Cache; +import org.ehcache.event.CacheEvent; +import org.ehcache.event.CacheEventListener; + +public final class EhcacheConsumer extends DefaultConsumer implements CacheEventListener<Object, Object> { + private final EhcacheConfiguration configuration; + private final EhcacheManager manager; + private final Cache<Object, Object> cache; + + public EhcacheConsumer(EhcacheEndpoint endpoint, EhcacheConfiguration configuration, Processor processor) throws Exception { + super(endpoint, processor); + + this.configuration = configuration; + this.manager = endpoint.getManager(); + this.cache = manager.getCache(); + } + + @Override + protected void doStart() throws Exception { + super.doStart(); + + this.cache.getRuntimeConfiguration().registerCacheEventListener( + this, + configuration.getEventOrdering(), + configuration.getEventFiring(), + configuration.getEventTypes() + ); + } + + @Override + protected void doStop() throws Exception { + cache.getRuntimeConfiguration().deregisterCacheEventListener(this); + + super.doStop(); + } + + @Override + public void onEvent(CacheEvent<Object, Object> event) { + final Exchange exchange = getEndpoint().createExchange(); + final Message message = exchange.getIn(); + + message.setHeader(EhcacheConstants.KEY, event.getKey()); + message.setHeader(EhcacheConstants.EVENT_TYPE, event.getType()); + message.setHeader(EhcacheConstants.OLD_VALUE, event.getOldValue()); + message.setBody(event.getNewValue()); + + try { + getProcessor().process(exchange); + } catch (Exception e) { + getExceptionHandler().handleException("Error processing exchange", exchange, e); + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheEndpoint.java ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheEndpoint.java b/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheEndpoint.java new file mode 100644 index 0000000..d2b019b --- /dev/null +++ b/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheEndpoint.java @@ -0,0 +1,84 @@ +/** + * 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.ehcache; + +import org.apache.camel.Consumer; +import org.apache.camel.Processor; +import org.apache.camel.Producer; +import org.apache.camel.impl.DefaultEndpoint; +import org.apache.camel.spi.Metadata; +import org.apache.camel.spi.UriEndpoint; +import org.apache.camel.spi.UriPath; + +@UriEndpoint(scheme = "ehcache", title = "Ehcache", syntax = "ehcache:cacheName", consumerClass = EhcacheConsumer.class, label = "cache,datagrid,clustering") +public class EhcacheEndpoint extends DefaultEndpoint { + @UriPath(description = "the cache name") + @Metadata(required = "true") + private final String cacheName; + + private final EhcacheConfiguration configuration; + private final EhcacheManager cacheManager; + + EhcacheEndpoint(String uri, EhcacheComponent component, EhcacheConfiguration configuration) throws Exception { + super(uri, component); + + this.cacheName = configuration.getCacheName(); + this.configuration = configuration; + this.cacheManager = new EhcacheManager(configuration); + } + + @Override + public Producer createProducer() throws Exception { + return new EhcacheProducer(this, configuration); + } + + @Override + public Consumer createConsumer(Processor processor) throws Exception { + return new EhcacheConsumer(this, configuration, processor); + } + + @Override + public boolean isSingleton() { + return true; + } + + @Override + protected void doStart() throws Exception { + cacheManager.start(); + super.doStart(); + } + + @Override + protected void doStop() throws Exception { + super.doStop(); + cacheManager.stop(); + } + + @Override + public EhcacheComponent getComponent() { + return (EhcacheComponent) super.getComponent(); + } + + EhcacheManager getManager() { + return cacheManager; + } + + EhcacheConfiguration getConfiguration() { + return configuration; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheManager.java ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheManager.java b/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheManager.java new file mode 100644 index 0000000..7cfb7d9 --- /dev/null +++ b/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheManager.java @@ -0,0 +1,99 @@ +/** + * 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.ehcache; + +import java.io.IOException; + +import org.apache.camel.Service; +import org.apache.camel.util.ObjectHelper; +import org.ehcache.Cache; +import org.ehcache.CacheManager; +import org.ehcache.config.CacheConfiguration; +import org.ehcache.config.ResourcePools; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.ehcache.config.builders.CacheConfigurationBuilder.newCacheConfigurationBuilder; + +public class EhcacheManager implements Service { + private static final Logger LOGGER = LoggerFactory.getLogger(EhcacheManager.class); + + private final EhcacheConfiguration configuration; + private final CacheManager cacheManager; + private final boolean managed; + + public EhcacheManager(EhcacheConfiguration configuration) throws IOException { + this(configuration.createCacheManager(), !configuration.hasCacheManager(), configuration); + } + + public EhcacheManager(CacheManager cacheManager) { + this(cacheManager, false, null); + } + + public EhcacheManager(CacheManager cacheManager, boolean managed) { + this(cacheManager, managed, null); + } + + private EhcacheManager(CacheManager cacheManager, boolean managed, EhcacheConfiguration configuration) { + this.cacheManager = cacheManager; + this.managed = managed; + this.configuration = configuration; + + ObjectHelper.notNull(cacheManager, "cacheManager"); + } + + @Override + public void start() throws Exception { + if (managed) { + cacheManager.init(); + } + } + + @Override + public void stop() throws Exception { + if (managed) { + cacheManager.close(); + } + } + + public <K, V> Cache<K, V> getCache(String name, Class<K> keyType, Class<V> valueType) throws Exception { + Cache<K, V> cache = cacheManager.getCache(name, keyType, valueType); + if (cache == null && configuration != null && configuration.isCreateCacheIfNotExist()) { + final CacheConfiguration config = configuration.getCacheConfiguration(name); + final ResourcePools pools = configuration.getResourcePools(name); + + if (config == null && pools == null) { + throw new IllegalArgumentException("No cache config and resource pools for cache " + name); + } + + cache = cacheManager.createCache( + name, + config != null + ? config + : newCacheConfigurationBuilder(keyType, valueType, pools).build() + ); + } + + return cache; + } + + public Cache<Object, Object> getCache() throws Exception { + ObjectHelper.notNull(configuration, "Ehcache configuration"); + + return getCache(configuration.getCacheName(), Object.class, Object.class); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheProducer.java ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheProducer.java b/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheProducer.java new file mode 100644 index 0000000..1015c66 --- /dev/null +++ b/components/camel-ehcache/src/main/java/org/apache/camel/component/ehcache/EhcacheProducer.java @@ -0,0 +1,203 @@ +/** + * 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.ehcache; + +import java.util.Map; +import java.util.Set; + +import org.apache.camel.CamelExchangeException; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.NoSuchHeaderException; +import org.apache.camel.impl.DefaultProducer; +import org.ehcache.Cache; + +public final class EhcacheProducer extends DefaultProducer { + private final EhcacheConfiguration configuration; + private final EhcacheManager manager; + private final Cache<Object, Object> cache; + + public EhcacheProducer(EhcacheEndpoint endpoint, EhcacheConfiguration configuration) throws Exception { + super(endpoint); + + this.configuration = configuration; + this.manager = endpoint.getManager(); + this.cache = manager.getCache(); + } + + @Override + public void process(Exchange exchange) throws Exception { + final Message message = exchange.getIn(); + final String action = exchange.getIn().getHeader(EhcacheConstants.ACTION, configuration.getAction(), String.class); + + if (action == null) { + throw new NoSuchHeaderException(exchange, EhcacheConstants.ACTION, String.class); + } + + switch (action) { + case EhcacheConstants.ACTION_CLEAR: + onClear(message); + break; + case EhcacheConstants.ACTION_PUT: + onPut(message); + break; + case EhcacheConstants.ACTION_PUT_ALL: + onPutAll(message); + break; + case EhcacheConstants.ACTION_PUT_IF_ABSENT: + onPutIfAbsent(message); + break; + case EhcacheConstants.ACTION_GET: + onGet(message); + break; + case EhcacheConstants.ACTION_GET_ALL: + onGetAll(message); + break; + case EhcacheConstants.ACTION_REMOVE: + onRemove(message); + break; + case EhcacheConstants.ACTION_REMOVE_ALL: + onRemoveAll(message); + break; + case EhcacheConstants.ACTION_REPLACE: + onReplace(message); + break; + default: + throw new IllegalStateException("Unsupported operation " + action); + } + } + + // **************************** + // Handlers + // **************************** + + private void onClear(Message message) throws Exception { + cache.clear(); + + setResult(message, true, null, null); + } + + private void onPut(Message message) throws Exception { + cache.put(getKey(message), getValue(message, Object.class)); + + setResult(message, true, null, null); + } + + private void onPutAll(Message message) throws Exception { + cache.putAll(getValue(message, Map.class)); + + setResult(message, true, null, null); + } + + private void onPutIfAbsent(Message message) throws Exception { + Object oldValue = cache.putIfAbsent(getKey(message), getValue(message, Object.class)); + + setResult(message, true, null, oldValue); + } + + private void onGet(Message message) throws Exception { + Object result = cache.get(getKey(message)); + + setResult(message, true, result, null); + } + + private void onGetAll(Message message) throws Exception { + Object result = cache.getAll(message.getHeader(EhcacheConstants.KEYS, Set.class)); + + setResult(message, true, result, null); + } + + private void onRemove(Message message) throws Exception { + boolean success = true; + Object valueToReplace = message.getHeader(EhcacheConstants.OLD_VALUE); + if (valueToReplace == null) { + cache.remove(getKey(message)); + } else { + success = cache.remove(getKey(message), valueToReplace); + } + + setResult(message, success, null, null); + } + + private void onRemoveAll(Message message) throws Exception { + cache.removeAll(message.getHeader(EhcacheConstants.KEYS, Set.class)); + + setResult(message, true, null, null); + } + + private void onReplace(Message message) throws Exception { + boolean success = true; + Object oldValue = null; + Object value = getValue(message, Object.class); + Object valueToReplace = message.getHeader(EhcacheConstants.OLD_VALUE); + if (valueToReplace == null) { + oldValue = cache.replace(getKey(message), value); + } else { + success = cache.replace(getKey(message), valueToReplace, value); + } + + setResult(message, success, null, oldValue); + } + + // **************************** + // Helpers + // **************************** + + private String getKey(final Message message) throws Exception { + String value = message.getHeader(EhcacheConstants.KEY, String.class); + if (value == null) { + value = configuration.getKey(); + } + + if (value == null) { + throw new CamelExchangeException( + "No value provided in header or as default value (" + EhcacheConstants.KEY + ")", + message.getExchange() + ); + } + + return value; + } + + private <T> T getValue(final Message message, final Class<T> type) throws Exception { + T value = message.getHeader(EhcacheConstants.VALUE, type); + if (value == null) { + value = message.getBody(type); + } + + if (value == null) { + throw new CamelExchangeException( + "No value provided in header or body (" + EhcacheConstants.VALUE + ")", + message.getExchange() + ); + } + + return value; + } + + private void setResult(Message message, boolean success, Object result, Object oldValue) { + message.setHeader(EhcacheConstants.ACTION_SUCCEEDED, success); + message.setHeader(EhcacheConstants.ACTION_HAS_RESULT, oldValue != null || result != null); + + if (oldValue != null) { + message.setHeader(EhcacheConstants.OLD_VALUE, oldValue); + } + if (result != null) { + message.setBody(result); + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/src/main/resources/META-INF/LICENSE.txt ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/src/main/resources/META-INF/LICENSE.txt b/components/camel-ehcache/src/main/resources/META-INF/LICENSE.txt new file mode 100644 index 0000000..6b0b127 --- /dev/null +++ b/components/camel-ehcache/src/main/resources/META-INF/LICENSE.txt @@ -0,0 +1,203 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/src/main/resources/META-INF/NOTICE.txt ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/src/main/resources/META-INF/NOTICE.txt b/components/camel-ehcache/src/main/resources/META-INF/NOTICE.txt new file mode 100644 index 0000000..2e215bf --- /dev/null +++ b/components/camel-ehcache/src/main/resources/META-INF/NOTICE.txt @@ -0,0 +1,11 @@ + ========================================================================= + == NOTICE file corresponding to the section 4 d of == + == the Apache License, Version 2.0, == + == in this case for the Apache Camel distribution. == + ========================================================================= + + This product includes software developed by + The Apache Software Foundation (http://www.apache.org/). + + Please read the different LICENSE files present in the licenses directory of + this distribution. http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/src/main/resources/META-INF/services/org/apache/camel/component/ehcache ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/src/main/resources/META-INF/services/org/apache/camel/component/ehcache b/components/camel-ehcache/src/main/resources/META-INF/services/org/apache/camel/component/ehcache new file mode 100644 index 0000000..93d6556 --- /dev/null +++ b/components/camel-ehcache/src/main/resources/META-INF/services/org/apache/camel/component/ehcache @@ -0,0 +1 @@ +class=org.apache.camel.component.ehcache.EhcacheComponent http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/src/test/java/org/apache/camel/component/ehcache/EhcacheConsumerTest.java ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/src/test/java/org/apache/camel/component/ehcache/EhcacheConsumerTest.java b/components/camel-ehcache/src/test/java/org/apache/camel/component/ehcache/EhcacheConsumerTest.java new file mode 100644 index 0000000..7412656 --- /dev/null +++ b/components/camel-ehcache/src/test/java/org/apache/camel/component/ehcache/EhcacheConsumerTest.java @@ -0,0 +1,71 @@ +/** + * 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.ehcache; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.ehcache.Cache; +import org.ehcache.event.EventType; +import org.junit.Test; + +public class EhcacheConsumerTest extends EhcacheTestSupport { + + @Test + public void testEvents() throws Exception { + String key = generateRandomString(); + String[] values = generateRandomArrayOfStrings(2); + + MockEndpoint created = getMockEndpoint("mock:created"); + created.expectedMinimumMessageCount(1); + created.expectedHeaderReceived(EhcacheConstants.KEY, key); + created.expectedHeaderReceived(EhcacheConstants.EVENT_TYPE, EventType.CREATED); + + MockEndpoint updated = getMockEndpoint("mock:updated"); + updated.expectedMinimumMessageCount(1); + updated.expectedHeaderReceived(EhcacheConstants.KEY, key); + updated.expectedHeaderReceived(EhcacheConstants.OLD_VALUE, values[0]); + updated.expectedHeaderReceived(EhcacheConstants.EVENT_TYPE, EventType.UPDATED); + + MockEndpoint all = getMockEndpoint("mock:all"); + all.expectedMinimumMessageCount(2); + all.expectedHeaderValuesReceivedInAnyOrder(EhcacheConstants.KEY, key, key); + all.expectedHeaderValuesReceivedInAnyOrder(EhcacheConstants.OLD_VALUE, null, values[0]); + all.expectedHeaderValuesReceivedInAnyOrder(EhcacheConstants.EVENT_TYPE, EventType.CREATED, EventType.UPDATED); + all.expectedBodiesReceived(values); + + Cache<Object, Object> cache = getCache(TEST_CACHE_NAME); + cache.put(key, values[0]); + cache.put(key, values[1]); + + assertMockEndpointsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + public void configure() { + fromF("ehcache://%s?cacheManager=#cacheManager&eventTypes=CREATED", TEST_CACHE_NAME) + .to("mock:created"); + fromF("ehcache://%s?cacheManager=#cacheManager&eventTypes=UPDATED", TEST_CACHE_NAME) + .to("mock:updated"); + fromF("ehcache://%s?cacheManager=#cacheManager", TEST_CACHE_NAME) + .to("mock:all"); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/src/test/java/org/apache/camel/component/ehcache/EhcacheProducerTest.java ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/src/test/java/org/apache/camel/component/ehcache/EhcacheProducerTest.java b/components/camel-ehcache/src/test/java/org/apache/camel/component/ehcache/EhcacheProducerTest.java new file mode 100644 index 0000000..395e8e7 --- /dev/null +++ b/components/camel-ehcache/src/test/java/org/apache/camel/component/ehcache/EhcacheProducerTest.java @@ -0,0 +1,361 @@ +/** + * 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.ehcache; + +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.ehcache.Cache; +import org.junit.Test; + +public class EhcacheProducerTest extends EhcacheTestSupport { + + // **************************** + // Clear + // **************************** + + @Test + public void testCacheClear() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(1); + mock.expectedBodiesReceived((Object)null); + mock.expectedHeaderReceived(EhcacheConstants.ACTION_HAS_RESULT, false); + mock.expectedHeaderReceived(EhcacheConstants.ACTION_SUCCEEDED, true); + + fluentTemplate() + .withHeader(EhcacheConstants.ACTION, EhcacheConstants.ACTION_CLEAR) + .to("direct://start") + .send(); + + assertMockEndpointsSatisfied(); + } + + // **************************** + // Put + // **************************** + + @Test + public void testCachePut() throws Exception { + final Cache<Object, Object> cache = getCache(TEST_CACHE_NAME); + final String key = generateRandomString(); + final String val = generateRandomString(); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(1); + mock.expectedBodiesReceived(val); + mock.expectedHeaderReceived(EhcacheConstants.ACTION_HAS_RESULT, false); + mock.expectedHeaderReceived(EhcacheConstants.ACTION_SUCCEEDED, true); + + fluentTemplate() + .withHeader(EhcacheConstants.ACTION, EhcacheConstants.ACTION_PUT) + .withHeader(EhcacheConstants.KEY, key) + .withBody(val) + .to("direct://start") + .send(); + + assertMockEndpointsSatisfied(); + + assertTrue(cache.containsKey(key)); + assertEquals(val, cache.get(key)); + } + + @Test + public void testCachePutAll() throws Exception { + final Cache<Object, Object> cache = getCache(TEST_CACHE_NAME); + final Map<String, String> map = generateRandomMapOfString(3); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(1); + mock.expectedHeaderReceived(EhcacheConstants.ACTION_HAS_RESULT, false); + mock.expectedHeaderReceived(EhcacheConstants.ACTION_SUCCEEDED, true); + + fluentTemplate() + .withHeader(EhcacheConstants.ACTION, EhcacheConstants.ACTION_PUT_ALL) + .withBody(map) + .to("direct://start") + .send(); + + assertMockEndpointsSatisfied(); + + map.forEach((k, v) -> { + assertTrue(cache.containsKey(k)); + assertEquals(v, cache.get(k)); + }); + } + + @Test + public void testCachePutIfAbsent() throws Exception { + final Cache<Object, Object> cache = getCache(TEST_CACHE_NAME); + final String key = generateRandomString(); + final String val1 = generateRandomString(); + final String val2 = generateRandomString(); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(2); + mock.expectedBodiesReceived(val1, val2); + mock.expectedHeaderValuesReceivedInAnyOrder(EhcacheConstants.ACTION_HAS_RESULT, false, true); + mock.expectedHeaderValuesReceivedInAnyOrder(EhcacheConstants.ACTION_SUCCEEDED, true, true); + mock.expectedHeaderValuesReceivedInAnyOrder(EhcacheConstants.OLD_VALUE, null, val1); + + fluentTemplate() + .clearHeaders() + .clearBody() + .withHeader(EhcacheConstants.ACTION, EhcacheConstants.ACTION_PUT_IF_ABSENT) + .withHeader(EhcacheConstants.KEY, key) + .withBody(val1) + .to("direct://start") + .send(); + fluentTemplate() + .clearHeaders() + .clearBody() + .withHeader(EhcacheConstants.ACTION, EhcacheConstants.ACTION_PUT_IF_ABSENT) + .withHeader(EhcacheConstants.KEY, key) + .withBody(val2) + .to("direct://start") + .send(); + + assertMockEndpointsSatisfied(); + + assertTrue(cache.containsKey(key)); + assertEquals(val1, cache.get(key)); + } + + // **************************** + // Get + // **************************** + + @Test + public void testCacheGet() throws Exception { + final Cache<Object, Object> cache = getCache(TEST_CACHE_NAME); + final String key = generateRandomString(); + final String val = generateRandomString(); + + cache.put(key, val); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(1); + mock.expectedBodiesReceived(val); + mock.expectedHeaderReceived(EhcacheConstants.ACTION_HAS_RESULT, true); + mock.expectedHeaderReceived(EhcacheConstants.ACTION_SUCCEEDED, true); + + fluentTemplate() + .withHeader(EhcacheConstants.ACTION, EhcacheConstants.ACTION_GET) + .withHeader(EhcacheConstants.KEY, key) + .withBody(val) + .to("direct://start") + .send(); + + assertMockEndpointsSatisfied(); + } + + @Test + public void testCacheGetAll() throws Exception { + final Cache<Object, Object> cache = getCache(TEST_CACHE_NAME); + final Map<String, String> map = generateRandomMapOfString(3); + final Set<String> keys = map.keySet().stream().limit(2).collect(Collectors.toSet()); + + cache.putAll(map); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(1); + mock.expectedHeaderReceived(EhcacheConstants.ACTION_HAS_RESULT, true); + mock.expectedHeaderReceived(EhcacheConstants.ACTION_SUCCEEDED, true); + + fluentTemplate() + .withHeader(EhcacheConstants.ACTION, EhcacheConstants.ACTION_GET_ALL) + .withHeader(EhcacheConstants.KEYS, keys) + .to("direct://start") + .send(); + + assertMockEndpointsSatisfied(); + + final Map<String, String> elements = mock.getExchanges().get(0).getIn().getBody(Map.class); + keys.forEach(k -> { + assertTrue(elements.containsKey(k)); + assertEquals(map.get(k), elements.get(k)); + }); + } + + // **************************** + // Remove + // **************************** + + @Test + public void testCacheRemove() throws Exception { + final Cache<Object, Object> cache = getCache(TEST_CACHE_NAME); + final String key = generateRandomString(); + final String val = generateRandomString(); + + cache.put(key, val); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(1); + mock.expectedHeaderReceived(EhcacheConstants.ACTION_HAS_RESULT, false); + mock.expectedHeaderReceived(EhcacheConstants.ACTION_SUCCEEDED, true); + + fluentTemplate() + .withHeader(EhcacheConstants.ACTION, EhcacheConstants.ACTION_REMOVE) + .withHeader(EhcacheConstants.KEY, key) + .to("direct://start") + .send(); + + assertMockEndpointsSatisfied(); + + assertFalse(cache.containsKey(key)); + } + + @Test + public void testCacheRemoveIf() throws Exception { + final Cache<Object, Object> cache = getCache(TEST_CACHE_NAME); + final String key = generateRandomString(); + final String val1 = generateRandomString(); + final String val2 = generateRandomString(); + + cache.put(key, val1); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(2); + mock.expectedHeaderValuesReceivedInAnyOrder(EhcacheConstants.ACTION_HAS_RESULT, false, false); + mock.expectedHeaderValuesReceivedInAnyOrder(EhcacheConstants.ACTION_SUCCEEDED, false, true); + + fluentTemplate() + .clearHeaders() + .clearBody() + .withHeader(EhcacheConstants.ACTION, EhcacheConstants.ACTION_REMOVE) + .withHeader(EhcacheConstants.KEY, key) + .withHeader(EhcacheConstants.OLD_VALUE, val2) + .to("direct://start") + .send(); + + assertTrue(cache.containsKey(key)); + + fluentTemplate() + .clearHeaders() + .clearBody() + .withHeader(EhcacheConstants.ACTION, EhcacheConstants.ACTION_REMOVE) + .withHeader(EhcacheConstants.KEY, key) + .withHeader(EhcacheConstants.OLD_VALUE, val1) + .to("direct://start") + .send(); + + assertMockEndpointsSatisfied(); + + assertFalse(cache.containsKey(key)); + } + + @Test + public void testCacheRemoveAll() throws Exception { + final Cache<Object, Object> cache = getCache(TEST_CACHE_NAME); + final Map<String, String> map = generateRandomMapOfString(3); + final Set<String> keys = map.keySet().stream().limit(2).collect(Collectors.toSet()); + + cache.putAll(map); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(1); + mock.expectedHeaderReceived(EhcacheConstants.ACTION_HAS_RESULT, false); + mock.expectedHeaderReceived(EhcacheConstants.ACTION_SUCCEEDED, true); + + fluentTemplate() + .withHeader(EhcacheConstants.ACTION, EhcacheConstants.ACTION_REMOVE_ALL) + .withHeader(EhcacheConstants.KEYS, keys) + .to("direct://start") + .send(); + + assertMockEndpointsSatisfied(); + + cache.forEach(e -> assertFalse(keys.contains(e.getKey()))); + } + + // **************************** + // Replace + // **************************** + + @Test + public void testCacheReplace() throws Exception { + final Cache<Object, Object> cache = getCache(TEST_CACHE_NAME); + final String key = generateRandomString(); + final String val1 = generateRandomString(); + final String val2 = generateRandomString(); + final String val3 = generateRandomString(); + + cache.put(key, val1); + + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMinimumMessageCount(3); + mock.expectedHeaderValuesReceivedInAnyOrder(EhcacheConstants.ACTION_HAS_RESULT, false, false, false); + mock.expectedHeaderValuesReceivedInAnyOrder(EhcacheConstants.ACTION_SUCCEEDED, true, false, true); + + assertEquals(val1, cache.get(key)); + + fluentTemplate() + .clearHeaders() + .clearBody() + .withHeader(EhcacheConstants.ACTION, EhcacheConstants.ACTION_REPLACE) + .withHeader(EhcacheConstants.KEY, key) + .withBody(val2) + .to("direct://start") + .send(); + + assertEquals(val2, cache.get(key)); + + fluentTemplate() + .clearHeaders() + .clearBody() + .withHeader(EhcacheConstants.ACTION, EhcacheConstants.ACTION_REPLACE) + .withHeader(EhcacheConstants.KEY, key) + .withHeader(EhcacheConstants.OLD_VALUE, val1) + .withBody(val3) + .to("direct://start") + .send(); + + assertEquals(val2, cache.get(key)); + + fluentTemplate() + .clearHeaders() + .clearBody() + .withHeader(EhcacheConstants.ACTION, EhcacheConstants.ACTION_REPLACE) + .withHeader(EhcacheConstants.KEY, key) + .withHeader(EhcacheConstants.OLD_VALUE, val2) + .withBody(val3) + .to("direct://start") + .send(); + + assertEquals(val3, cache.get(key)); + + assertMockEndpointsSatisfied(); + } + + // **************************** + // Route + // **************************** + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + public void configure() { + from("direct://start") + .toF("ehcache://%s?cacheManager=#cacheManager", TEST_CACHE_NAME) + .to("log:org.apache.camel.component.ehcache?level=INFO&showAll=true&multiline=true") + .to("mock:result"); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/src/test/java/org/apache/camel/component/ehcache/EhcacheTestSupport.java ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/src/test/java/org/apache/camel/component/ehcache/EhcacheTestSupport.java b/components/camel-ehcache/src/test/java/org/apache/camel/component/ehcache/EhcacheTestSupport.java new file mode 100644 index 0000000..82dfdd7 --- /dev/null +++ b/components/camel-ehcache/src/test/java/org/apache/camel/component/ehcache/EhcacheTestSupport.java @@ -0,0 +1,105 @@ +/** + * 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.ehcache; + +import java.net.URL; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.apache.camel.builder.FluentProducerTemplate; +import org.apache.camel.impl.JndiRegistry; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.ehcache.Cache; +import org.ehcache.CacheManager; +import org.ehcache.config.Configuration; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.xml.XmlConfiguration; +import org.junit.Rule; +import org.junit.rules.TestName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EhcacheTestSupport extends CamelTestSupport { + public static final Logger LOGGER = LoggerFactory.getLogger(EhcacheTestSupport.class); + public static final String EHCACHE_CONFIG = "/ehcache/ehcache-config.xml"; + public static final String TEST_CACHE_NAME = "mycache"; + + @Rule + public final TestName testName = new TestName(); + public CacheManager cacheManager; + + @Override + protected void doPreSetup() throws Exception { + final URL url = this.getClass().getResource(EHCACHE_CONFIG); + final Configuration xmlConfig = new XmlConfiguration(url); + + cacheManager = CacheManagerBuilder.newCacheManager(xmlConfig); + cacheManager.init(); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + + if (cacheManager != null) { + cacheManager.close(); + } + } + + @Override + protected JndiRegistry createRegistry() throws Exception { + JndiRegistry registry = super.createRegistry(); + registry.bind("cacheManager", cacheManager); + + return registry; + } + + protected Cache<Object, Object> getCache(String name) { + return cacheManager.getCache(name, Object.class, Object.class); + } + + protected String generateRandomString() { + return UUID.randomUUID().toString(); + } + + protected String[] generateRandomArrayOfStrings(int size) { + String[] array = new String[size]; + Arrays.setAll(array, i -> generateRandomString()); + + return array; + } + + protected List<String> generateRandomListOfStrings(int size) { + return Arrays.asList(generateRandomArrayOfStrings(size)); + } + + protected Map<String, String> generateRandomMapOfString(int size) { + return IntStream.range(0, size).boxed().collect(Collectors.toMap( + i -> i + "-" + generateRandomString(), + i -> i + "-" + generateRandomString() + )); + } + + FluentProducerTemplate fluentTemplate() { + return FluentProducerTemplate.on(context()); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/src/test/resources/ehcache/ehcache-config.xml ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/src/test/resources/ehcache/ehcache-config.xml b/components/camel-ehcache/src/test/resources/ehcache/ehcache-config.xml new file mode 100644 index 0000000..c0e7822 --- /dev/null +++ b/components/camel-ehcache/src/test/resources/ehcache/ehcache-config.xml @@ -0,0 +1,34 @@ +<!-- + ~ 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. + --> +<ehcache:config + xmlns:ehcache="http://www.ehcache.org/v3" + xmlns:jcache="http://www.ehcache.org/v3/jsr107"> + + <ehcache:cache alias="mycache" uses-template="default-template"> + <ehcache:key-type>java.lang.Object</ehcache:key-type> + <ehcache:value-type>java.lang.Object</ehcache:value-type> + </ehcache:cache> + + <ehcache:cache-template name="default-template"> + <ehcache:expiry> + <ehcache:none/> + </ehcache:expiry> + + <ehcache:heap unit="entries">100</ehcache:heap> + </ehcache:cache-template> + +</ehcache:config> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/camel-ehcache/src/test/resources/log4j.properties ---------------------------------------------------------------------- diff --git a/components/camel-ehcache/src/test/resources/log4j.properties b/components/camel-ehcache/src/test/resources/log4j.properties new file mode 100644 index 0000000..2cb2227 --- /dev/null +++ b/components/camel-ehcache/src/test/resources/log4j.properties @@ -0,0 +1,21 @@ +# +# The logging properties used +# +log4j.rootLogger=INFO, file + +# uncomment the following line to turn on Camel debugging +#log4j.logger.org.apache.camel=DEBUG +log4j.logger.org.apache.camel.component.ehcache=DEBUG + +# CONSOLE appender not used by default +log4j.appender.out=org.apache.log4j.ConsoleAppender +log4j.appender.out.layout=org.apache.log4j.PatternLayout +log4j.appender.out.layout.ConversionPattern=[%30.30t] %-30.30c{1} %-5p %m%n +#log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n + +# File appender +log4j.appender.file=org.apache.log4j.FileAppender +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n +log4j.appender.file.file=target/camel-ehcache-test.log +log4j.appender.file.append=true \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/components/pom.xml ---------------------------------------------------------------------- diff --git a/components/pom.xml b/components/pom.xml index 87997197..b6001b5 100644 --- a/components/pom.xml +++ b/components/pom.xml @@ -96,6 +96,7 @@ <module>camel-dozer</module> <module>camel-dropbox</module> <module>camel-eclipse</module> + <module>camel-ehcache</module> <module>camel-ejb</module> <module>camel-elasticsearch</module> <module>camel-elsql</module> http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/parent/pom.xml ---------------------------------------------------------------------- diff --git a/parent/pom.xml b/parent/pom.xml index d5eb6f5..2a5c596 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -151,9 +151,10 @@ <easymock-version>3.2</easymock-version> <eclipse-compiler-version>4.2.2</eclipse-compiler-version> <eclipse-equinox-common-version>3.3.0-v20070426</eclipse-equinox-common-version> - <ehcache-version>2.10.1</ehcache-version> <egit-github-core-version>2.1.5</egit-github-core-version> <egit-github-core-bundle-version>2.1.5_1</egit-github-core-bundle-version> + <ehcache-version>2.10.1</ehcache-version> + <ehcache3-version>3.0.1</ehcache3-version> <elasticsearch-bundle-version>2.3.1_1</elasticsearch-bundle-version> <elasticsearch-guava-version>18.0</elasticsearch-guava-version> <elasticsearch-version>2.3.1</elasticsearch-version> @@ -897,6 +898,11 @@ </dependency> <dependency> <groupId>org.apache.camel</groupId> + <artifactId>camel-ehcache</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> <artifactId>camel-ejb</artifactId> <version>${project.version}</version> </dependency> http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/platforms/karaf/features/src/main/resources/features.xml ---------------------------------------------------------------------- diff --git a/platforms/karaf/features/src/main/resources/features.xml b/platforms/karaf/features/src/main/resources/features.xml index 6542670..c8a5624 100644 --- a/platforms/karaf/features/src/main/resources/features.xml +++ b/platforms/karaf/features/src/main/resources/features.xml @@ -399,6 +399,11 @@ <bundle dependency='true'>wrap:mvn:com.squareup.okio/okio/${squareup-okio-version}</bundle> <bundle>mvn:org.apache.camel/camel-dropbox/${project.version}</bundle> </feature> + <feature name='camel-ehcache' version='${project.version}' resolver='(obr)' start-level='50'> + <feature version="${project.version}">camel-core</feature> + <bundle dependency="true">mvn:org.ehcache/ehcache/${ehcache3-version}</bundle> + <bundle>mvn:org.apache.camel/camel-ehcache/${project.version}</bundle> + </feature> <feature name='camel-elsql' version='${project.version}' resolver='(obr)' start-level='50'> <feature version="${project.version}">camel-sql</feature> <bundle dependency="true">mvn:com.opengamma/elsql/${elsql-version}</bundle> http://git-wip-us.apache.org/repos/asf/camel/blob/9a473f39/tests/camel-itest-karaf/src/test/java/org/apache/camel/itest/karaf/CamelEhcacheTest.java ---------------------------------------------------------------------- diff --git a/tests/camel-itest-karaf/src/test/java/org/apache/camel/itest/karaf/CamelEhcacheTest.java b/tests/camel-itest-karaf/src/test/java/org/apache/camel/itest/karaf/CamelEhcacheTest.java new file mode 100644 index 0000000..0e5b418 --- /dev/null +++ b/tests/camel-itest-karaf/src/test/java/org/apache/camel/itest/karaf/CamelEhcacheTest.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.camel.itest.karaf; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.junit.PaxExam; + +@RunWith(PaxExam.class) +public class CamelEhcacheTest extends BaseKarafTest { + + public static final String COMPONENT = "ehcache"; + + @Test + public void test() throws Exception { + testComponent(COMPONENT); + } + + +}