title: Trying to use EhCache using Spring and a custom GenericDao interface that extends the Hibernate's JpaRepository
body: <p><strong>Background</strong></p>
  
  <p>Here is my working (simplified) <code>GenericDao</code> interface, which is implemented by any <code>DomainDao</code>:</p>
  
  <p><em>GenericDao.java</em></p>
  
  <pre class="lang-java prettyprint-override"><code>@NoRepositoryBean
  public interface GenericDao&lt;E extends Persistable&lt;K&gt;, K extends Serializable&gt; extends JpaRepository&lt;E, K&gt; {
  
      public List&lt;E&gt; findAll();
  
      public E persist(E entity);
  
  }
  </code></pre>
  
  <p><em>GenericDaoImpl.java</em></p>
  
  <pre class="lang-java prettyprint-override"><code>public class GenericDaoImpl&lt;E extends Persistable&lt;K&gt;, K extends Serializable&gt; extends SimpleJpaRepository&lt;E, K&gt; implements GenericDao&lt;E, K&gt; {
  
      private final JpaEntityInformation&lt;E, ?&gt; entityInformation;
      private final EntityManager em;
      private final Class&lt;E&gt; type;
  
      public GenericDaoImpl(JpaEntityInformation&lt;E, ?&gt; entityInformation, EntityManager em) {
          super(entityInformation, em);
          this.entityInformation = entityInformation;
          this.em = em;
          this.type = entityInformation.getJavaType();
      }
  
      @Override
      public List&lt;E&gt; findAll() {
          return super.findAll();
      }
  
      @Override
      @Transactional
      public E persist(E entity) {
          if (entityInformation.isNew(entity) || !EntityUtils.isPrimaryKeyGenerated(type) &amp;&amp; !em.contains(entity)) {
              em.persist(entity);
          }
          return entity;
      }
  
  }
  </code></pre>
  
  <p>For example, to manage the domains <code>Foo</code> and <code>Bar</code>, you just need to create two interfaces as follow:</p>
  
  <p><em>FooDao.java</em></p>
  
  <pre class="lang-java prettyprint-override"><code>public interface FooDao extends GenericDao&lt;Foo, Integer&gt; {
  
  }
  </code></pre>
  
  <p><em>BarDao.java</em></p>
  
  <pre class="lang-java prettyprint-override"><code>public interface BarDao extends GenericDao&lt;Bar, Integer&gt; {
  
  }
  </code></pre>
  
  <p>The <a href="http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/beans/factory/annotation/Autowired.html" rel="nofollow"><code>@Autowired</code></a> annotation of <code>Spring</code> will automatically instantiate a <code>GenericDaoImpl</code> with the good entity and primary key types.</p>
  
  <hr>
  
  <p><strong>Problem</strong></p>
  
  <p>I'm now trying to add a caching process on my DAOs, using EhCache and the <a href="http://code.google.com/p/ehcache-spring-annotations/" rel="nofollow">EhCache Spring Annotations</a> model.</p>
  
  <p><em>GenericDao.java</em></p>
  
  <pre class="lang-java prettyprint-override"><code>@NoRepositoryBean
  public interface GenericDao&lt;E extends Persistable&lt;K&gt;, K extends Serializable&gt; extends JpaRepository&lt;E, K&gt; {
  
      @Cacheable(cacheName = "dao")
      public List&lt;E&gt; findAll();
  
      @TriggersRemove(cacheName = "dao")
      public E persist(E entity);
  
  }
  </code></pre>
  
  <p><em>applicationContext.xml</em></p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;ehcache:annotation-driven cache-manager="ehCacheManager" /&gt;    
  &lt;bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" /&gt;
  </code></pre>
  
  <p><em>ehcache.xml</em></p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;cache name="dao"
      eternal="false"
      maxElementsInMemory="10000"
      overflowToDisk="false"
      timeToIdleSeconds="86400"
      timeToLiveSeconds="86400"
      memoryStoreEvictionPolicy="LFU" /&gt;
  </code></pre>
  
  <p>The problem with the use of a <code>GenericDao</code>, is that the cache should manage each <code>DomainDao</code> independently of each other. For example, with the current configuration, if I call <code>fooDao.findAll()</code>, and then <code>barDao.persist(new Bar())</code>, the cache generated by <code>fooDao.findAll()</code> will be reset, since the same cache would have been used (i.e. <code>&lt;cache name="dao" /&gt;</code>), while it shouldn't.</p>
  
  <hr>
  
  <p><strong>Trails</strong></p>
  
  <p>I tried to implement my own <a href="http://code.google.com/p/ehcache-spring-annotations/wiki/CacheKeyGenerators" rel="nofollow"><code>CacheKeyGenerator</code></a>, that will take into account the type of the calling <code>DomainDao</code>:</p>
  
  <p><em>applicationContext.xml</em></p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;ehcache:annotation-driven cache-manager="ehCacheManager" default-cache-key-generator="daoCacheKeyGenerator" /&gt;    
  &lt;bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" /&gt;
  &lt;bean id="daoCacheKeyGenerator" class="myapp.dao.support.DaoCacheKeyGenerator" /&gt;
  </code></pre>
  
  <p><em>DaoCacheKeyGenerator.java</em></p>
  
  <pre class="lang-java prettyprint-override"><code>public class DaoCacheKeyGenerator implements CacheKeyGenerator&lt;DaoCacheKey&gt; {
  
      @Override
      public DaoCacheKey generateKey(MethodInvocation methodInvocation) {
          Class&lt;?&gt; clazz = methodInvocation.getThis().getClass().getInterfaces()[0];
          Method method = methodInvocation.getMethod();
          String methodName = method.getName();
          Class&lt;?&gt;[] parameterClasses = method.getParameterTypes();
          return new DaoCacheKey(clazz, methodName, parameterClasses);
      }
  
      @Override
      public DaoCacheKey generateKey(Object... data) {
          return null;
      }
  }
  </code></pre>
  
  <p><em>DaoCacheKey.java</em></p>
  
  <pre class="lang-java prettyprint-override"><code>public class DaoCacheKey implements Serializable {
  
      private static final long serialVersionUID = 338466521373614710L;
  
      private Class&lt;?&gt; clazz;
      private String methodName;
      private Class&lt;?&gt;[] parameterClasses;
  
      public DaoCacheKey(Class&lt;?&gt; clazz, String methodName, Class&lt;?&gt;[] parameterClasses) {
          this.clazz = clazz;
          this.methodName = methodName;
          this.parameterClasses = parameterClasses;
      }
  
      @Override
      public boolean equals(Object obj) { // &lt;-- breakpoint
          if (obj instanceof DaoCacheKey) {
              DaoCacheKey other = (DaoCacheKey) obj;
              if (clazz.equals(other.clazz)) {
                  // if @TriggersRemove, reset any cache generated by a find* method of the same DomainDao
                  boolean removeCache = !methodName.startsWith("find") &amp;&amp; other.methodName.startsWith("find");
                  // if @Cacheable, check if the result has been previously cached
                  boolean getOrCreateCache = methodName.equals(other.methodName) &amp;&amp; Arrays.deepEquals(parameterClasses, other.parameterClasses);
                  return removeCache || getOrCreateCache;
              }
          }
          return false;
      }
  
      @Override
      public int hashCode() { // &lt;-- breakpoint
          return super.hashCode();
      }
  
  }
  </code></pre>
  
  <p>The problem with the above <code>DaoCacheKey</code>, is that the <code>equals</code> method get never called (the program never breaks at least), but the <code>hashCode</code> one does, so the algorithm can't get applied.</p>
  
  <hr>
  
  <p><strong>Question</strong></p>
  
  <p>Has anyone already managed such a cache? If yes how? Does my try is relevant? If yes, how to make the <code>equals</code> method called, instead of the <code>hashCode</code> one? By extending an existing <a href="http://code.google.com/p/ehcache-spring-annotations/wiki/CacheKeyGenerators" rel="nofollow"><code>CacheKeyGenerator</code></a>? If yes, which one?</p>