Introduction

Using an XML file you can configure a CacheManager at creation time, according to this schema definition.

<config> root element

The root element of our XML configuration. One <config> element in an XML file provides the definition for a CacheManager.

Ehcache allows for creating multiple CacheManager instances using the same XML configuration file. In contrast to the JSR-107 javax.cache.spi.CachingProvider, Ehcache does not maintain a registry of CacheManager instances.

<service> elements

<service> elements are extension points for specifying services managed by the CacheManager.

Each Service defined in this way is managed with the same lifecycle as the CacheManager — for each Service defined for a CacheManager, the Service.start is called during CacheManager.init processing and the Service.stop method is called during CacheManager.close processing.

These Service instances can then be used by Cache instances managed by the CacheManager.

JSR-107 uses this extension point of the XML configuration (and Ehcache 3’s modular architecture), as explained in the JSR-107 configuration section.

<default-serializers> element

A <default-serializers> element represents Serializers configured at CacheManager level. It is a collection of <serializer> elements that require a type and a fully qualified class name of the Serializer.

<default-copiers> element

A <default-copiers> element represents Copiers configured at CacheManager level. It is a collection of <copier> elements that requires a type and a fully qualified class name of the Copier.

<persistence> element

A <persistence> element represents Persistence, to be used when creating a PersistentCacheManager. It requires the directory location where data needs be stored on disk.

<cache> elements

A <cache> element represent a Cache instance that will be created and managed by the CacheManager. Each <cache> requires the alias attribute, used at runtime to retrieve the corresponding Cache<K, V> instance using the org.ehcache.CacheManager.getCache(String, Class<K>, Class<V>) method. The optional uses-template attribute lets you reference a <cache-template> element’s name attribute. See the cache-template section for further details on using them.

Supported nested elements are optional:

  1. <key-type>: the fully qualified class name (FQCN) of the keys (<K>) held in the Cache<K, V>; defaults to java.lang.Object

  2. <value-type>: FQCN of the values (<V>) held in the Cache; defaults to java.lang.Object

  3. <expiry>: control the expiry type and its parameters

  4. <eviction-advisor>: FQCN of a org.ehcache.config.EvictionAdvisor<K, V> implementation, defaults to null, i.e. none

  5. <integration>: configure a CacheLoaderWriter for a cache-through pattern

  6. <resources>: configure the tiers and their capacity. When using on-heap only, you can replace this element by the <heap> one.

<cache-template> elements

<cache-template> elements represent a uniquely named (specified using the mandatory name attribute) template for <cache> elements to inherit from. A <cache> element that references a <cache-template> by its name using the uses-template attribute, will inherit all properties of the <cache-template>. A <cache> can override these properties as required.

A <cache-template> element may contain all the same child elements as a <cache> element.

We’ve set up a complete configuration example to inspire you.
Processing of cache template configurations can be triggered lazily by actions that dynamically bind new caches to existing cache templates. Errors within such templates may not be revealed until this lazy processing is triggered.

Property replacement in XML configuration files

Java system properties can be referenced inside XML configuration files. The property value will replace the property reference during the configuration parsing.

This is done by using the ${prop.name} syntax. It is supported in all attributes and elements values that accept the ${} characters as legal characters. This currently rules out all numbers, mostly used in sizing things, and identifiers, such as cache and template names.

If the system property does not exist, this will make the configuration parsing fail.

A classical use case for this feature is for disk files location inside the directory attribute of the persistence tag:

<persistence directory="${user.home}/cache-data"/> (1)
1 Here user.home will be replaced by the value of the system property, something like /home/user

XML programmatic parsing

If you are obtaining your CacheManager through the JSR-107 API, what follows is done automatically when invoking javax.cache.spi.CachingProvider.getCacheManager(java.net.URI, java.lang.ClassLoader).
final URL myUrl = getClass().getResource("/configs/docs/getting-started.xml"); (1)
XmlConfiguration xmlConfig = new XmlConfiguration(myUrl); (2)
CacheManager myCacheManager = CacheManagerBuilder.newCacheManager(xmlConfig); (3)
myCacheManager.init();  (4)
1 Obtain a URL to your XML file’s location
2 Instantiate an XmlConfiguration passing the XML file’s URL to it
3 Using the static org.ehcache.config.builders.CacheManagerBuilder.newCacheManager(org.ehcache.config.Configuration) allows you to create your CacheManager instance using the Configuration from the XmlConfiguration.
4 Initialize the cacheManager before it is used.

We can also use <cache-template> declared in the XML file to seed instances of CacheConfigurationBuilder. In order to use a <cache-template> element from an XML file, e.g. the /my-config.xml contains this XML fragment:

<cache-template name="example">
  <key-type>java.lang.Long</key-type>
  <value-type>java.lang.String</value-type>
  <heap unit="entries">200</heap>
</cache-template>

Creating a CacheConfigurationBuilder of that example <cache-template> element, would be done as follows:

XmlConfiguration xmlConfiguration = new XmlConfiguration(getClass().getResource("/configs/docs/template-sample.xml"));
CacheConfigurationBuilder<Long, String> configurationBuilder = xmlConfiguration.newCacheConfigurationBuilderFromTemplate("example", Long.class, String.class); (1)
configurationBuilder = configurationBuilder.withResourcePools(ResourcePoolsBuilder.heap(1000)); (2)
1 Creates a builder, inheriting the capacity constraint of 200 entries
2 The inherent properties can be overridden by simply providing a different value prior to building the CacheConfiguration

Programmatic configuration to XML

Just like getting a cache manager configuration from its XML equivalent, the reverse translation is supported too. You can instantiate an XmlConfiguration object by passing the cache manager Configuration and the string representation of that object will give you the XML equivalent of the provided Configuration.

XmlConfiguration xmlConfiguration = new XmlConfiguration(getClass().getResource("/configs/docs/template-sample.xml"));
CacheConfigurationBuilder<Long, String> configurationBuilder = xmlConfiguration.newCacheConfigurationBuilderFromTemplate("example", Long.class, String.class); (1)
configurationBuilder = configurationBuilder.withResourcePools(ResourcePoolsBuilder.heap(1000)); (2)
1 Creates a builder, inheriting the capacity constraint of 200 entries
2 The inherent properties can be overridden by simply providing a different value prior to building the CacheConfiguration
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
  .with(CacheManagerBuilder.persistence(tmpDir.newFile("myData")))
  .withCache("threeTieredCache",
    CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
      ResourcePoolsBuilder.newResourcePoolsBuilder()
        .heap(10, EntryUnit.ENTRIES)
        .offheap(1, MemoryUnit.MB)
        .disk(20, MemoryUnit.MB, true))
      .withExpiry(ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofSeconds(20)))
  ).build(false);

Configuration configuration = cacheManager.getRuntimeConfiguration();
XmlConfiguration xmlConfiguration = new XmlConfiguration(configuration);  (1)
String xml = xmlConfiguration.toString(); (2)
1 Instantiate an XmlConfiguration passing the cache manager Configuration
2 Retrieve the XML representation using the toString method.

Not every programmatic configuration can be translated to its XML equivalent in this manner. Translation is not supported if the cache manager configuration contains a cache with any one of the following configured:

  1. EvictionAdvisor

  2. A custom ExpiryPolicy other than timeToLiveExpiration or timeToIdleExpiration from ExpiryPolicyBuilder`

  3. Using an instance of the following instead of their classes:

    1. Serializer

    2. Copier

    3. CacheLoaderWriter

    4. CacheEventListener

    5. ResilienceStrategy

Multiple XML Configurations In One Document

The XmlMultiConfiguration class and the associated ehcache-multi.xsd XML schema provide support for multiple Ehcache configurations to be housed within a single XML container format.

Multiple Ehcache Manager Configurations

The simplest use of the multi-configuration features is to embed multiple cache manager configurations in a single xml file:

<multi:configurations
  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
  xmlns='http://www.ehcache.org/v3'
  xmlns:multi='http://www.ehcache.org/v3/multi'
  xsi:schemaLocation='http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core.xsd
  http://www.ehcache.org/v3/multi http://www.ehcache.org/schema/ehcache-multi.xsd'> (1)

  <multi:configuration identity="foo-manager"> (2)
    <config>
      <cache alias="foo">
        <key-type>java.lang.String</key-type>
        <value-type>java.lang.String</value-type>
        <resources>
          <heap unit="entries">20</heap>
          <offheap unit="MB">10</offheap>
        </resources>
      </cache>
    </config>
  </multi:configuration>

  <multi:configuration identity="bar-manager">
    <config>
      <cache alias="bar">
        <key-type>java.lang.String</key-type>
        <value-type>java.lang.String</value-type>
        <resources>
          <heap unit="entries">20</heap>
          <offheap unit="MB">10</offheap>
        </resources>
      </cache>
    </config>
  </multi:configuration>
</multi:configurations>
1 A top-level <configurations> container with namespace declarations for the multi and core schemas
2 Each Ehcache configuration is embedded inside a configuration tag with a required (unique) identity attribute

These embedded configurations can then be retrieved via an XmlMultiConfiguration instance built from the XML document.

XmlMultiConfiguration multipleConfiguration = XmlMultiConfiguration
  .from(getClass().getResource("/configs/docs/multi/multiple-managers.xml")) (1)
  .build(); (2)

Configuration fooConfiguration = multipleConfiguration.configuration("foo-manager"); (3)
1 The XmlMultiConfiguration is assembled from the XML resource.
2 Once assembled the configuration is built.
3 Configuration instances can then be retrieved using their identities.

Multiple Cache Manager Variants

Multiple variant configurations for a given manager can be provided by including a sequence of <variant> tags, each with a required type attribute:

<multi:configuration identity="foo-manager">
  <multi:variant type="heap">
    <config>
      <cache alias="foo">
        <key-type>java.lang.String</key-type>
        <value-type>java.lang.String</value-type>
        <resources>
          <heap unit="entries">1000</heap>
        </resources>
      </cache>
    </config>
  </multi:variant>
  <multi:variant type="offheap">
    <config>
      <cache alias="foo">
        <key-type>java.lang.String</key-type>
        <value-type>java.lang.String</value-type>
        <resources>
          <heap unit="entries">1000</heap>
          <offheap unit="MB">128</offheap>
        </resources>
      </cache>
    </config>
  </multi:variant>
</multi:configuration>

A specific cache configuration can then be retrieved by choosing both a variant and an identity explicitly on retrieval.

XmlMultiConfiguration variantConfiguration = XmlMultiConfiguration
  .from(getClass().getResource("/configs/docs/multi/multiple-variants.xml"))
  .build();

Configuration fooConfiguration = variantConfiguration.configuration("foo-manager", "offheap"); (1)

The samples above are just samples, variant types can be used to represent any kind of variation: development vs production, clustered vs unclustered, red vs blue, etc.

Configurations with multiple variants must have a variant type specified when they are retrieved otherwise an IllegalStateException will be thrown. Configurations without multiple variants will always return their single configuration for all requested variants.

Multiple Cache Manager Retrieval

Multiple cache managers can be retrieved from an XmlMultiConfiguration by iterating over the configurations identities():

Map<String, Configuration> allConfigurations = multipleConfiguration.identities().stream() (1)
  .collect(Collectors.toMap(i -> i, i -> multipleConfiguration.configuration(i))); (2)
Map<String, Configuration> offheapConfigurations = variantConfiguration.identities().stream()
  .collect(Collectors.toMap(i -> i, i -> variantConfiguration.configuration(i, "offheap"))); (3)
1 From a stream over the set of identities in a mult-configuration.
2 Map each identity to it’s unique (non-varianted) configuration.
3 Alternatively, map each identity to a specific variant configuration.

Building XML Multi Configurations

XmlMultiConfiguration instance can be assembled and modified using the associated builder API. The previous examples of parsing XML multi-configuration documents are all just simple invocations of the richer builder API.

Configurations can be built from scratch as show below:

XmlMultiConfiguration multiConfiguration = XmlMultiConfiguration.fromNothing() (1)
  .withManager("bar", barConfiguration) (2)
  .withManager("foo").variant("heap", heapConfiguration).variant("offheap", offheapConfiguration) (3)
  .build(); (4)
1 Starting with an initially empty set of configurations.
2 Add a configuration without variants.
3 Add a configuration with two different variants: heap and offheap.
4 Build the final configuration instance.

They can also be built from existing configurations:

XmlMultiConfiguration modified = XmlMultiConfiguration.from(multiConfiguration) (1)
  .withManager("foo") (2)
  .build();
1 Starting with an existing XmlMultiConfiguration.
2 Remove the configuration with identity "foo".

Once built a multi-configuration can be retrieved in XML form:

String xmlString = multiConfiguration.asRenderedDocument(); (1)
Document xmlDocument = multiConfiguration.asDocument(); (2)
1 Retrieving the XML as a rendered string.
2 Retrieving the XML as a DOM (org.w3c.Document).