JBoss.orgCommunity Documentation

Chapter 57. eXo Cache

57.1. Basic concepts
57.2. eXo Cache extension
57.3. eXo Cache based on JBoss Cache
57.3.1. Configuring the ExoCacheFactory
57.3.2. Adding specific configuration for a cache
57.3.3. Adding a cache creator
57.3.4. Defining a cache
57.4. eXo Cache based on Infinispan
57.4.1. Configure the ExoCacheFactory
57.4.2. Add specific configuration for a cache
57.4.3. Add a cache creator
57.4.4. Define an infinispan cache instance

All applications on the top of eXo JCR that need a cache, can rely on an org.exoplatform.services.cache.ExoCache instance that is managed by the org.exoplatform.services.cache.CacheService. The main implementation of this service is org.exoplatform.services.cache.impl.CacheServiceImpl which depends on the org.exoplatform.services.cache.ExoCacheConfig in order to create new ExoCache instances. See the below example of org.exoplatform.services.cache.CacheService definition:

  <component>
    <key>org.exoplatform.services.cache.CacheService</key>
    <jmx-name>cache:type=CacheService</jmx-name>
    <type>org.exoplatform.services.cache.impl.CacheServiceImpl</type>
    <init-params>
      <object-param>
        <name>cache.config.default</name>
        <description>The default cache configuration</description>
        <object type="org.exoplatform.services.cache.ExoCacheConfig">
          <field name="name"><string>default</string></field>
          <field name="maxSize"><int>300</int></field>
          <field name="liveTime"><long>600</long></field>
          <field name="distributed"><boolean>false</boolean></field>
          <field name="implementation"><string>org.exoplatform.services.cache.concurrent.ConcurrentFIFOExoCache</string></field> 
        </object>
      </object-param>
    </init-params>
  </component>

See the below example about how to define a new ExoCacheConfig thanks to a external-component-plugin:

  <external-component-plugins>
    <target-component>org.exoplatform.services.cache.CacheService</target-component>
    <component-plugin>
      <name>addExoCacheConfig</name>
      <set-method>addExoCacheConfig</set-method>
      <type>org.exoplatform.services.cache.ExoCacheConfigPlugin</type>
      <description>Configures the cache for query service</description>
      <init-params>
        <object-param>
          <name>cache.config.wcm.composer</name>
          <description>The default cache configuration</description>
          <object type="org.exoplatform.services.cache.ExoCacheConfig">
            <field name="name"><string>wcm.composer</string></field>
            <field name="maxSize"><int>300</int></field>
            <field name="liveTime"><long>600</long></field>
            <field name="distributed"><boolean>false</boolean></field>
            <field name="implementation"><string>org.exoplatform.services.cache.concurrent.ConcurrentFIFOExoCache</string></field> 
          </object>
        </object-param>
      </init-params>
    </component-plugin>
  </external-component-plugins>

In the previous versions of eXo kernel, it was quite complex to implement your own ExoCache because it was not open enough. Since kernel 2.0.8, it is possible to easily integrate your favorite cache provider in eXo Products.

You just need to implement your own ExoCacheFactory and register it in an eXo container, as described below:

package org.exoplatform.services.cache;
...
public interface ExoCacheFactory {
  
  /**
   * Creates a new instance of {@link org.exoplatform.services.cache.ExoCache}
   * @param config the cache to create
   * @return the new instance of {@link org.exoplatform.services.cache.ExoCache}
   * @exception ExoCacheInitException if an exception happens while initializing the cache
   */
  public ExoCache createCache(ExoCacheConfig config) throws ExoCacheInitException;  
}

As you can see, there is only one method to implement which can be seen as a converter of an ExoCacheConfig to get an instance of ExoCache. Once, you created your own implementation, you can simply register your factory by adding a file conf/portal/configuration.xml with a content of the following type:

<configuration>
  <component>
    <key>org.exoplatform.services.cache.ExoCacheFactory</key>
    <type>org.exoplatform.tutorial.MyExoCacheFactoryImpl</type>
    ...
  </component>   
</configuration>

When you add, the eXo library in your classpath, the eXo service container will use the default configuration provided in the library itself but of course you can still redefined the configuration if you wish as you can do with any components.

The default configuration of the factory is:

<configuration>  
  <component>
    <key>org.exoplatform.services.cache.ExoCacheFactory</key>
    <type>org.exoplatform.services.cache.impl.jboss.ExoCacheFactoryImpl</type>
    <init-params>
      <value-param>
        <name>cache.config.template</name>
        <value>jar:/conf/portal/cache-configuration-template.xml</value>
      </value-param>
      <value-param>
        <name>allow.shareable.cache</name>
        <value>true</value>
      </value-param>
    </init-params>
  </component>   
</configuration>

The factory for jboss cache, delegates the cache creation to ExoCacheCreator that is defined as below:

package org.exoplatform.services.cache.impl.jboss;
...
public interface ExoCacheCreator {

  /**
   * Creates an eXo cache according to the given configuration {@link org.exoplatform.services.cache.ExoCacheConfig}
   * @param config the configuration of the cache to apply
   * @param cache the cache to initialize
   * @exception ExoCacheInitException if an exception happens while initializing the cache
   */
  public ExoCache create(ExoCacheConfig config, Cache<Serializable, Object> cache) throws ExoCacheInitException;
  
  /**
   * Returns the type of {@link org.exoplatform.services.cache.ExoCacheConfig} expected by the creator  
   * @return the expected type
   */
  public Class<? extends ExoCacheConfig> getExpectedConfigType();
  
  /**
   * Returns the name of the implementation expected by the creator. This is mainly used to be backward compatible
   * @return the expected by the creator
   */
  public String getExpectedImplementation();
}

The ExoCacheCreator allows you to define any kind of jboss cache instance that you would like to have. It has been designed to give you the ability to have your own type of configuration and to always be backward compatible.

In an ExoCacheCreator, you need to implement 3 methods which are:

By default, no cache creator are defined, so you need to define them yourself by adding them in your configuration files.

You have 2 ways to define a cache which are:

The factory for infinispan, delegates the cache creation to ExoCacheCreator that is defined as below:

package org.exoplatform.services.cache.impl.infinispan;
...
public interface ExoCacheCreator {

   /**
    * Creates an eXo cache according to the given configuration {@link org.exoplatform.services.cache.ExoCacheConfig}
    * @param config the configuration of the cache to apply
    * @param cacheConfig the configuration of the infinispan cache
    * @param cacheGetter a {@link Callable} instance from which we can get the cache
    * @exception ExoCacheInitException if an exception happens while initializing the cache
    */
   public ExoCache<Serializable, Object> create(ExoCacheConfig config, Configuration cacheConfig, Callable<Cache<Serializable, Object>> cacheGetter) throws ExoCacheInitException;

   /**
    * Returns the type of {@link org.exoplatform.services.cache.ExoCacheConfig} expected by the creator  
    * @return the expected type
    */
   public Class<? extends ExoCacheConfig> getExpectedConfigType();

   /**
    * Returns a set of all the implementations expected by the creator. This is mainly used to be backward compatible
    * @return the expected by the creator
    */
   public Set<String> getExpectedImplementations();
}

The ExoCacheCreator allows you to define any kind of infinispan cache instance that you would like to have. It has been designed to give you the ability to have your own type of configuration and to always be backward compatible.

In an ExoCacheCreator, you need to implement 3 methods which are:

By default, no cache creator are defined, so you need to define them yourself by adding them in your configuration files.

This is the generic cache creator that allows you to use any eviction strategies defined by default in Infinispan.

..
<object-param>
  <name>GENERIC</name>
  <description>The generic cache creator</description>
  <object type="org.exoplatform.services.cache.impl.infinispan.generic.GenericExoCacheCreator">
    <field name="implementations">
      <collection type="java.util.HashSet">
         <value>
            <string>NONE</string>
         </value>
         <value>
            <string>FIFO</string>
         </value>
         <value>
            <string>LRU</string>
         </value>
         <value>
            <string>UNORDERED</string>
         </value>
         <value>
            <string>LIRS</string>
         </value>
      </collection>        
    </field>
    <field name="defaultStrategy"><string>${my-value}</string></field>
    <field name="defaultMaxIdle"><long>${my-value}</long></field>
    <field name="defaultWakeUpInterval"><long>${my-value}</long></field>
  </object>
</object-param>
...

All the eviction strategies proposed by default in infinispan rely on the generic cache creator.