blob: aa4e4cf710b54c3d39bc9089df0d071d190cb6c6 [file]
= Ehcache Component
:doctitle: Ehcache
:shortname: ehcache
:artifactid: camel-ehcache
:description: Perform caching operations using Ehcache.
:since: 2.18
:supportlevel: Stable
:tabs-sync-option:
:component-header: Both producer and consumer are supported
*Since Camel {since}*
*{component-header}*
The Ehcache component enables you to perform caching operations using
Ehcache 3 as the Cache Implementation.
The Cache consumer is an event based consumer and can be used to listen
and respond to specific cache activities.
Maven users will need to add the following dependency to
their `pom.xml` for this component:
[source,xml]
----
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-ehcache</artifactId>
<version>x.x.x</version>
<!-- use the same version as your Camel core version -->
</dependency>
----
== URI format
----
ehcache://cacheName[?options]
----
// component options: START
include::partial$component-configure-options.adoc[]
include::partial$component-endpoint-options.adoc[]
include::partial$component-endpoint-headers.adoc[]
// component options: END
== Examples
=== Using the cache in a route
The producer runs the action of the `CamelEhcacheAction` header (or of the `action` option) with the key of the
`CamelEhcacheKey` header. A PUT stores the message body. A GET sets the value as the message body, and the header
`CamelEhcacheActionHasResult` tells whether the key was found:
[source,yaml]
----
- route:
from:
uri: direct:save-order
steps:
- setHeader:
name: CamelEhcacheAction
expression:
constant:
expression: PUT
- setHeader:
name: CamelEhcacheKey
expression:
simple:
expression: "${header.orderId}"
- to:
uri: ehcache:orders
- route:
from:
uri: direct:find-order
steps:
- setHeader:
name: CamelEhcacheAction
expression:
constant:
expression: GET
- setHeader:
name: CamelEhcacheKey
expression:
simple:
expression: "${header.orderId}"
- to:
uri: ehcache:orders
- choice:
when:
- expression:
simple:
expression: "${header.CamelEhcacheActionHasResult}"
steps:
- log:
message: "Order ${header.orderId} from the cache: ${body}"
otherwise:
steps:
- log:
message: "Order ${header.orderId} is not in the cache"
----
NOTE: Without a cache manager or a cache configuration, each endpoint creates its own cache.
`ehcache:orders?action=PUT` and `ehcache:orders?action=GET` are then two different caches.
Set the action in a header and use one endpoint, as above, or share a cache manager with `configurationUri`,
`cacheManager` or `cacheManagerConfiguration`.
The consumer receives cache events only when the cache comes from a configuration or a cache manager.
The default cache of an endpoint has no events. In this example, both endpoints use the same `ehcache.xml`,
so they share its cache manager:
[source,yaml]
----
- route:
from:
uri: direct:save-order
steps:
- setHeader:
name: CamelEhcacheKey
expression:
simple:
expression: "${header.orderId}"
- to:
uri: ehcache:orders
parameters:
configurationUri: classpath:ehcache.xml
action: PUT
- route:
from:
uri: ehcache:orders
parameters:
configurationUri: classpath:ehcache.xml
eventTypes: CREATED
steps:
- log:
message: "New order ${header.CamelEhcacheKey}: ${body}"
----
The `ehcache.xml` file configures the cache:
[source,xml]
----
<config xmlns="http://www.ehcache.org/v3">
<cache alias="orders">
<heap unit="entries">1000</heap>
</cache>
</config>
----
=== Ehcache based idempotent repository example:
._Java-only: programmatic CacheManager and idempotent repository configuration_
[source,java]
----
CacheManager manager = CacheManagerBuilder.newCacheManager(new XmlConfiguration("ehcache.xml"));
EhcacheIdempotentRepository repo = new EhcacheIdempotentRepository(manager, "idempotent-cache");
from("direct:in")
.idempotentConsumer(header("messageId"), repo)
.to("mock:out");
----
=== Ehcache based aggregation repository example:
._Java-only: full test class with aggregation repository configuration_
[source,java]
----
public class EhcacheAggregationRepositoryRoutesTest extends CamelTestSupport {
private static final String ENDPOINT_MOCK = "mock:result";
private static final String ENDPOINT_DIRECT = "direct:one";
private static final int[] VALUES = generateRandomArrayOfInt(10, 0, 30);
private static final int SUM = IntStream.of(VALUES).reduce(0, (a, b) -> a + b);
private static final String CORRELATOR = "CORRELATOR";
@EndpointInject(ENDPOINT_MOCK)
private MockEndpoint mock;
@Produce(uri = ENDPOINT_DIRECT)
private ProducerTemplate producer;
@Test
public void checkAggregationFromOneRoute() throws Exception {
mock.expectedMessageCount(VALUES.length);
mock.expectedBodiesReceived(SUM);
IntStream.of(VALUES).forEach(
i -> producer.sendBodyAndHeader(i, CORRELATOR, CORRELATOR)
);
mock.assertIsSatisfied();
}
private Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
if (oldExchange == null) {
return newExchange;
} else {
Integer n = newExchange.getIn().getBody(Integer.class);
Integer o = oldExchange.getIn().getBody(Integer.class);
Integer v = (o == null ? 0 : o) + (n == null ? 0 : n);
oldExchange.getIn().setBody(v, Integer.class);
return oldExchange;
}
}
@Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
from(ENDPOINT_DIRECT)
.routeId("AggregatingRouteOne")
.aggregate(header(CORRELATOR))
.aggregationRepository(createAggregateRepository())
.aggregationStrategy(EhcacheAggregationRepositoryRoutesTest.this::aggregate)
.completionSize(VALUES.length)
.to("log:org.apache.camel.component.ehcache.processor.aggregate.level=INFO&showAll=true&mulltiline=true")
.to(ENDPOINT_MOCK);
}
};
}
protected EhcacheAggregationRepository createAggregateRepository() throws Exception {
CacheManager cacheManager = CacheManagerBuilder.newCacheManager(new XmlConfiguration("ehcache.xml"));
cacheManager.init();
EhcacheAggregationRepository repository = new EhcacheAggregationRepository();
repository.setCacheManager(cacheManager);
repository.setCacheName("aggregate");
return repository;
}
}
----