[[Cache-CacheComponent]]
Cache Component
~~~~~~~~~~~~~~~

*Available as of Camel 2.1*

The *cache* component enables you to perform caching operations using
EHCache as the Cache Implementation. The cache itself is created on
demand or if a cache of that name already exists then it is simply
utilized with its original settings.

This component supports producer and event based consumer endpoints.

The Cache consumer is an event based consumer and can be used to listen
and respond to specific cache activities. If you need to perform
selections from a pre-existing cache, use the processors defined for the
cache component.

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-cache</artifactId>
    <version>x.x.x</version>
    <!-- use the same version as your Camel core version -->
</dependency>
------------------------------------------------------------

[[Cache-URIformat]]
URI format
^^^^^^^^^^

[source,java]
---------------------------
cache://cacheName[?options]
---------------------------

You can append query options to the URI in the following format,
`?option=value&option=#beanRef&...`

[[Cache-Options]]
Options
^^^^^^^

[width="100%",cols="10%,10%,80%",options="header",]
|=======================================================================
|Name |Default Value |Description

|`maxElementsInMemory` |`1000` |The number of elements that may be stored in the defined cache

|`memoryStoreEvictionPolicy` |`MemoryStoreEvictionPolicy.LFU` |The number of elements that may be stored in the defined cache. Options
include

* MemoryStoreEvictionPolicy.LFU - Least frequently used
* MemoryStoreEvictionPolicy.LRU - Least recently used
* MemoryStoreEvictionPolicy.FIFO - first in first out, the oldest
element by creation time

|`overflowToDisk` |`true` |Specifies whether cache may overflow to disk

|`eternal` |`false` |Sets whether elements are eternal. If eternal, timeouts are ignored and
the +
 element never expires.

|`timeToLiveSeconds` |`300` |The maximum time between creation time and when an element expires. +
 Is used only if the element is not eternal

|`timeToIdleSeconds` |`300` |The maximum amount of time between accesses before an element expires

|`diskPersistent` |`false` |Whether the disk store persists between restarts of the Virtual Machine.

|`diskExpiryThreadIntervalSeconds` |`120` |The number of seconds between runs of the disk expiry thread.

|`cacheManagerFactory` |`null` |*Camel 2.8:* If you want to use a custom factory which instantiates and
creates the EHCache `net.sf.ehcache.CacheManager`.  
 _Type:_ abstract org.apache.camel.component.cache.CacheManagerFactory

|`eventListenerRegistry` |`null` |*Camel 2.8:* Sets a list of EHCache
`net.sf.ehcache.event.CacheEventListener` for all new caches- no need to
define it per cache in EHCache xml config anymore.  
 _Type:_ org.apache.camel.component.cache.CacheEventListenerRegistry

|`cacheLoaderRegistry` |`null` |*Camel 2.8:* Sets a list of
`org.apache.camel.component.cache.CacheLoaderWrapper` that extends
EHCache `net.sf.ehcache.loader.CacheLoader` for all new caches- no need
to define it per cache in EHCache xml config anymore.  
 _Type:_ org.apache.camel.component.cache.CacheLoaderRegistry

|`key` |`null` |*Camel 2.10:* To configure using a cache key by default. If a key is
provided in the message header, then the key from the header takes
precedence.

|`operation` |`null` |*Camel 2.10:* To configure using an cache operation by default. If an
operation in the message header, then the operation from the header
takes precedence.

|`objectCache` |`false` |*Camel 2.15:* Whether to turn on allowing to store non serializable
objects in the cache. If this option is enabled then overflow to disk
cannot be enabled as well.
|=======================================================================

[[Cache-CacheComponentoptions]]
Cache Component options
^^^^^^^^^^^^^^^^^^^^^^^

[width="100%",cols="10%,10%,80%",options="header",]
|=======================================================================
|Name |Default Value |Description

|`configuration` |  | To use a custom `org.apache.camel.component.cache.CacheConfiguration`
configuration.

|`cacheManagerFactory` |  | To use a custom `org.apache.camel.component.cache.CacheManagerFactory`.

|`configurationFile` |  | *Camel 2.13/2.12.3:* To configure the location of the `ehcache.xml` file
to use, such as `classpath:com/foo/mycache.xml` to load from classpath.
If no configuration is given, then the default settings from EHCache is
used.
|=======================================================================

[[Cache-SendingReceivingMessagestofromthecache]]
Sending/Receiving Messages to/from the cache
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[[Cache-MessageHeadersuptoCamel2.7]]
Message Headers up to Camel 2.7
+++++++++++++++++++++++++++++++

[width="100%",cols="20%,80%",options="header",]
|=======================================================================
|Header |Description

|`CACHE_OPERATION` |The operation to be performed on the cache. Valid options are

* GET
* CHECK
* ADD
* UPDATE
* DELETE
* DELETEALL +
 `GET` and `CHECK` requires *Camel 2.3* onwards.

|`CACHE_KEY` |The cache key used to store the Message in the cache. The cache key is
optional if the CACHE_OPERATION is DELETEALL
|=======================================================================
[[Cache-MessageHeadersCamel2.8]]
Message Headers Camel 2.8+
++++++++++++++++++++++++++

[Info]
====
Header changes in Camel 2.8

The header names and supported values have changed to be prefixed with
'CamelCache' and use mixed case. This makes them easier to identify and
keep separate from other headers. The CacheConstants variable names
remain unchanged, just their values have been changed. Also, these
headers are now removed from the exchange after the cache operation is
performed.

====

[width="100%",cols="20%,80%",options="header",]
|=======================================================================
|Header |Description

|`CamelCacheOperation` |The operation to be performed on the cache. The valid options are

* CamelCacheGet
* CamelCacheCheck
* CamelCacheAdd
* CamelCacheUpdate
* CamelCacheDelete
* CamelCacheDeleteAll

|`CamelCacheKey` |The cache key used to store the Message in the cache. The cache key is
optional if the CamelCacheOperation is CamelCacheDeleteAll
|=======================================================================

The `CamelCacheAdd` and `CamelCacheUpdate` operations support additional
headers:

[width="100%",cols="10%,10%,80%",options="header",]
|=======================================================================
|Header |Type |Description

|`CamelCacheTimeToLive` |`Integer` |*Camel 2.11:* Time to live in seconds.

|`CamelCacheTimeToIdle` |`Integer` |*Camel 2.11:* Time to idle in seconds.

|`CamelCacheEternal` |`Boolean` |*Camel 2.11:* Whether the content is eternal.
|=======================================================================

[[Cache-CacheProducer]]
Cache Producer
++++++++++++++

Sending data to the cache involves the ability to direct payloads in
exchanges to be stored in a pre-existing or created-on-demand cache. The
mechanics of doing this involve

* setting the Message Exchange Headers shown above.
* ensuring that the Message Exchange Body contains the message directed
to the cache

[[Cache-CacheConsumer]]
Cache Consumer
++++++++++++++

Receiving data from the cache involves the ability of the CacheConsumer
to listen on a pre-existing or created-on-demand Cache using an event
Listener and receive automatic notifications when any cache activity
take place (i.e
CamelCacheGet/CamelCacheUpdate/CamelCacheDelete/CamelCacheDeleteAll).
Upon such an activity taking place

* an exchange containing Message Exchange Headers and a Message Exchange
Body containing the just added/updated payload is placed and sent.
* in case of a CamelCacheDeleteAll operation, the Message Exchange
Header CamelCacheKey and the Message Exchange Body are not populated.

[[Cache-CacheProcessors]]
Cache Processors
++++++++++++++++

There are a set of nice processors with the ability to perform cache
lookups and selectively replace payload content at the

* body
* token
* xpath level

[[Cache-CacheUsageSamples]]
Cache Usage Samples
^^^^^^^^^^^^^^^^^^^

[[Cache-Example1:Configuringthecache]]
Example 1: Configuring the cache
++++++++++++++++++++++++++++++++

[source,java]
-------------------------------------------------
from("cache://MyApplicationCache" +
          "?maxElementsInMemory=1000" +
          "&memoryStoreEvictionPolicy=" +
              "MemoryStoreEvictionPolicy.LFU" +
          "&overflowToDisk=true" +
          "&eternal=true" +
          "&timeToLiveSeconds=300" +
          "&timeToIdleSeconds=true" +
          "&diskPersistent=true" +
          "&diskExpiryThreadIntervalSeconds=300")
-------------------------------------------------

[[Cache-Example2:Addingkeystothecache]]
Example 2: Adding keys to the cache
+++++++++++++++++++++++++++++++++++

[source,java]
---------------------------------------------------------------------------------------------
RouteBuilder builder = new RouteBuilder() {
    public void configure() {
     from("direct:start")
     .setHeader(CacheConstants.CACHE_OPERATION, constant(CacheConstants.CACHE_OPERATION_ADD))
     .setHeader(CacheConstants.CACHE_KEY, constant("Ralph_Waldo_Emerson"))
     .to("cache://TestCache1")
   }
};
---------------------------------------------------------------------------------------------

[[Cache-Example2:Updatingexistingkeysinacache]]
Example 2: Updating existing keys in a cache
++++++++++++++++++++++++++++++++++++++++++++

[source,java]
------------------------------------------------------------------------------------------------
RouteBuilder builder = new RouteBuilder() {
    public void configure() {
     from("direct:start")
     .setHeader(CacheConstants.CACHE_OPERATION, constant(CacheConstants.CACHE_OPERATION_UPDATE))
     .setHeader(CacheConstants.CACHE_KEY, constant("Ralph_Waldo_Emerson"))
     .to("cache://TestCache1")
   }
};
------------------------------------------------------------------------------------------------

[[Cache-Example3:Deletingexistingkeysinacache]]
Example 3: Deleting existing keys in a cache
++++++++++++++++++++++++++++++++++++++++++++

[source,java]
--------------------------------------------------------------------------------------
RouteBuilder builder = new RouteBuilder() {
    public void configure() {
     from("direct:start")
     .setHeader(CacheConstants.CACHE_OPERATION, constant(CacheConstants.CACHE_DELETE))
     .setHeader(CacheConstants.CACHE_KEY", constant("Ralph_Waldo_Emerson"))
     .to("cache://TestCache1")
   }
};
--------------------------------------------------------------------------------------

[[Cache-Example4:Deletingallexistingkeysinacache]]
Example 4: Deleting all existing keys in a cache
++++++++++++++++++++++++++++++++++++++++++++++++

[source,java]
-----------------------------------------------------------------------------------------
RouteBuilder builder = new RouteBuilder() {
    public void configure() {
     from("direct:start")
     .setHeader(CacheConstants.CACHE_OPERATION, constant(CacheConstants.CACHE_DELETEALL))
     .to("cache://TestCache1");
    }
};
-----------------------------------------------------------------------------------------

[[Cache-Example5:NotifyinganychangesregisteringinaCachetoProcessorsandotherProducers]]
Example 5: Notifying any changes registering in a Cache to Processors and other Producers
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

[source,java]
--------------------------------------------------------------------------------------------------
RouteBuilder builder = new RouteBuilder() {
    public void configure() {
     from("cache://TestCache1")
     .process(new Processor() {
        public void process(Exchange exchange)
               throws Exception {
           String operation = (String) exchange.getIn().getHeader(CacheConstants.CACHE_OPERATION);
           String key = (String) exchange.getIn().getHeader(CacheConstants.CACHE_KEY);
           Object body = exchange.getIn().getBody();
           // Do something
        }
     })
   }
};
--------------------------------------------------------------------------------------------------

[[Cache-Example6:UsingProcessorstoselectivelyreplacepayloadwithcachevalues]]
Example 6: Using Processors to selectively replace payload with cache values
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

[source,java]
---------------------------------------------------------------------------------------
RouteBuilder builder = new RouteBuilder() {
   public void configure() {
     //Message Body Replacer
     from("cache://TestCache1")
     .filter(header(CacheConstants.CACHE_KEY).isEqualTo("greeting"))
     .process(new CacheBasedMessageBodyReplacer("cache://TestCache1","farewell"))
     .to("direct:next");

    //Message Token replacer
    from("cache://TestCache1")
    .filter(header(CacheConstants.CACHE_KEY).isEqualTo("quote"))
    .process(new CacheBasedTokenReplacer("cache://TestCache1","novel","#novel#"))
    .process(new CacheBasedTokenReplacer("cache://TestCache1","author","#author#"))
    .process(new CacheBasedTokenReplacer("cache://TestCache1","number","#number#"))
    .to("direct:next");

    //Message XPath replacer
    from("cache://TestCache1").
    .filter(header(CacheConstants.CACHE_KEY).isEqualTo("XML_FRAGMENT"))
    .process(new CacheBasedXPathReplacer("cache://TestCache1","book1","/books/book1"))
    .process (new CacheBasedXPathReplacer("cache://TestCache1","book2","/books/book2"))
    .to("direct:next");
   }
};
---------------------------------------------------------------------------------------

[[Cache-Example7:GettinganentryfromtheCache]]
Example 7: Getting an entry from the Cache
++++++++++++++++++++++++++++++++++++++++++

[source,java]
------------------------------------------------------------------------------------------------
from("direct:start")
    // Prepare headers
    .setHeader(CacheConstants.CACHE_OPERATION, constant(CacheConstants.CACHE_OPERATION_GET))
    .setHeader(CacheConstants.CACHE_KEY, constant("Ralph_Waldo_Emerson")).
    .to("cache://TestCache1").
    // Check if entry was not found
    .choice().when(header(CacheConstants.CACHE_ELEMENT_WAS_FOUND).isNull()).
        // If not found, get the payload and put it to cache
        .to("cxf:bean:someHeavyweightOperation").
        .setHeader(CacheConstants.CACHE_OPERATION, constant(CacheConstants.CACHE_OPERATION_ADD))
        .setHeader(CacheConstants.CACHE_KEY, constant("Ralph_Waldo_Emerson"))
        .to("cache://TestCache1")
    .end()
    .to("direct:nextPhase");
------------------------------------------------------------------------------------------------

[[Cache-Example8:CheckingforanentryintheCache]]
Example 8: Checking for an entry in the Cache
+++++++++++++++++++++++++++++++++++++++++++++

Note: The CHECK command tests existence of an entry in the cache but
doesn't place a message in the body.

[source,java]
------------------------------------------------------------------------------------------------
from("direct:start")
    // Prepare headers
    .setHeader(CacheConstants.CACHE_OPERATION, constant(CacheConstants.CACHE_OPERATION_CHECK))
    .setHeader(CacheConstants.CACHE_KEY, constant("Ralph_Waldo_Emerson")).
    .to("cache://TestCache1").
    // Check if entry was not found
    .choice().when(header(CacheConstants.CACHE_ELEMENT_WAS_FOUND).isNull()).
        // If not found, get the payload and put it to cache
        .to("cxf:bean:someHeavyweightOperation").
        .setHeader(CacheConstants.CACHE_OPERATION, constant(CacheConstants.CACHE_OPERATION_ADD))
        .setHeader(CacheConstants.CACHE_KEY, constant("Ralph_Waldo_Emerson"))
        .to("cache://TestCache1")
    .end();
------------------------------------------------------------------------------------------------

[[Cache-ManagementofEHCache]]
Management of EHCache
^^^^^^^^^^^^^^^^^^^^^

http://ehcache.org/[EHCache] has its own statistics and management from
link:camel-jmx.html[JMX].

Here's a snippet on how to expose them via JMX in a Spring application
context:

[source,xml]
-----------------------------------------------------------------------------------------------------------------------------
<bean id="ehCacheManagementService" class="net.sf.ehcache.management.ManagementService" init-method="init" lazy-init="false">
  <constructor-arg>
    <bean class="net.sf.ehcache.CacheManager" factory-method="getInstance"/>
  </constructor-arg>
  <constructor-arg>
    <bean class="org.springframework.jmx.support.JmxUtils" factory-method="locateMBeanServer"/>
  </constructor-arg>
  <constructor-arg value="true"/>
  <constructor-arg value="true"/>
  <constructor-arg value="true"/>
  <constructor-arg value="true"/>
</bean>
-----------------------------------------------------------------------------------------------------------------------------

Of course you can do the same thing in straight Java:

[source,java]
--------------------------------------------------------------------------------------------------
ManagementService.registerMBeans(CacheManager.getInstance(), mbeanServer, true, true, true, true);
--------------------------------------------------------------------------------------------------

You can get cache hits, misses, in-memory hits, disk hits, size stats
this way. You can also change CacheConfiguration parameters on the fly.

[[Cache-CachereplicationCamel2.8]]
Cache replication Camel 2.8
^^^^^^^^^^^^^^^^^^^^^^^^^^^

The Camel Cache component is able to distribute a cache across server
nodes using several different replication mechanisms including: RMI,
JGroups, JMS and Cache Server.

There are two different ways to make it work:

*1.* You can configure `ehcache.xml` manually

OR

*2.* You can configure these three options:

* cacheManagerFactory
* eventListenerRegistry
* cacheLoaderRegistry

Configuring Camel Cache replication using the first option is a bit of
hard work as you have to configure all caches separately. So in a
situation when the all names of caches are not known, using
`ehcache.xml` is not a good idea.

The second option is much better when you want to use many different
caches as you do not need to define options per cache. This is because
replication options are set per `CacheManager` and per `CacheEndpoint`.
Also it is the only way when cache names are not know at the development
phase.

[Note]
====


It might be useful to read the http://ehcache.org/documentation[EHCache
manual] to get a better understanding of the Camel Cache replication
mechanism.

====

[[Cache-Example:JMScachereplication]]
Example: JMS cache replication
++++++++++++++++++++++++++++++

JMS replication is the most powerful and secured replication method.
Used together with Camel Cache replication makes it also rather
simple. An example is available on link:cachereplicationjmsexample.html[a
separate page].

