EhCache Con Spring

De Dos Ideas.
Saltar a: navegación, buscar

Spring Framework se integra perfectamente con EhCache, tanto sea a través de clases utilitarias "oficiales" como usando librerías adicionales que brindan una mejor integración.

Integración usando Spring Modules

El proyecto Spring Modules tiene módulos, agregados y herramientas de integración para Spring Framework. Spring Modules consiste en un conjunto de varios jar. En particular, el archivo spring-modules-ehcache.jar brinda soporte adicional para EhCache.

Usando esta integración resulta muy simple configurar EhCache dentro de Spring, y crear proxies de nuestros objetos a través de la configuración.

Ejemplo

Supongamos el siguiente objeto de prueba:

package com.dosideas.cache;

public class Contador {

   private int contador = 0;
   
   public int siguiente() {
       return contador++;
   }

}

Crearemos un archivo de configuración config.xml de Spring que tendrá un proxy de caché referenciando a este objeto. De esta manera, EhCache se encargará de cachear todas las invocaciones al objeto Contador.

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ehcache="http://www.springmodules.org/schema/ehcache" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springmodules.org/schema/ehcache http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd">

   <ehcache:config configLocation="classpath:ehcache.xml" />
   <ehcache:proxy id="cache.contador">
       <bean class="com.dosideas.cache.Contador"/>
       <ehcache:caching cacheName="dosIdeas" methodName="*"/>
   </ehcache:proxy>

</beans>

Estamos usando dos tags propios de la extensión spring-modules-ehcache. El tag ehcache:config hace referencia al archivo de configuración de ehcache, el cual define las regiones de caché.

El tag ehcache:proxy se encarga de crear un proxy del bean indicado dentro de este tag. En este caso, cuando pidamos un bean cache.contador tendremos un proxy de nuestro objeto Contador, el cual se encargará de usar la región de caché dosIdeas para la invocación de todos sus métodos.

El archivo de configuración ehcache.xml es muy simple, definomos el caché por default y una región "dosideas" que expira en 1 segundo: <?xml version="1.0" encoding="UTF-8"?> <ehcache>

   <diskStore path="java.io.tmpdir"/>
   <defaultCache
           maxElementsInMemory="10000"
           eternal="false"
           timeToIdleSeconds="120"
           timeToLiveSeconds="120"
           overflowToDisk="true"
           maxElementsOnDisk="10000000"
           diskPersistent="false"
           diskExpiryThreadIntervalSeconds="120"
           memoryStoreEvictionPolicy="LRU"
           />
   <cache name="dosIdeas"
          maxElementsInMemory="10000"
          maxElementsOnDisk="1000"
          eternal="false"
          overflowToDisk="true"
          timeToIdleSeconds="300"
          timeToLiveSeconds="1"
          memoryStoreEvictionPolicy="LFU"
           />

</ehcache>

Ejecutando el ejemplo

Creamos un test JUnit para realizar la prueba: package com.dosideas.cache;

@ContextConfiguration(locations={"classpath:config.xml"}) public class ContadorTest extends AbstractJUnit4SpringContextTests {

   @Autowired
   private Contador contador;
   @Test
   public void testSiguiente() {
       System.out.println("siguiente");
       for (int i = 0; i < 10; i++) {
           System.out.println("Siguiente: " + contador.siguiente());
       }
   }

}

Como el objeto Contador tiene un proxy caché, al ejecutar esta prueba veremos que todas las invocaciones devuelven "0". Podemos agregar un sleep para probar la expiración del cache:

   @Test
   public void testSiguiente() throws InterruptedException {
       System.out.println("siguiente");
       for (int i = 0; i < 10; i++) {
           System.out.println("Siguiente: " + contador.siguiente());
           if (i == 5) {
               Thread.sleep(1500);
           }
       }
   }

En este último caso, la mitad de las invocaciones devolverán "0". luego hacemos una pausa de 1500 milisegundos, lo que ocasiona la expiración del caché. A continuación, el resto de las invocaciones devuelve "1".

Administración y monitoreo de EhCache con JMX y Spring

El paquete net.sf.ehcache.management contiene Mbeans y un ManagementService para la administración y monitoreo de ehcache. Para hacer uso de estos debemos integrarlo con los archivos de configuración de Spring de esta manera:

   <ehcache:config configLocation="classpath:ehcache.xml" />
   <bean id="mbeanServer" class="org.springframework.jndi.JndiObjectFactoryBean">
      <property name="jndiName" value="java:comp/env/jmx/runtime"/>
   </bean>
   <bean class="net.sf.ehcache.management.ManagementService" init-method="init">
       <constructor-arg ref="cacheManager" />  //bean que creará ehcache:config
       <constructor-arg ref="mbeanServer" /> 
       <constructor-arg value="true" />        //registerCacheManager 
       <constructor-arg value="true" />        //registerCaches 
       <constructor-arg value="true" />        //registerCacheConfigurations 
       <constructor-arg value="true" />        //registerCacheStatistics 
   </bean>

De esta manera podríamos cambiar la configuración del cache sin necesidad de tener que deployar nuestra aplicación nuevamente usando por ejemplo JConsole o JManage. También podremos acceder a la información estadística del uso del cache (CacheHits, CacheMisses, DiskStoreObjectCount, InMemoryHits, OnDiskHits, StatisticsAccuracyDescription, ObjectCount).

Ver también