Cache collision and ehcache spring annotations module

If you are looking for a way to implement declarative caching with Spring, there is no way around Ehcache Spring Annotations [1]. This superimposes a transparent aspect on methods of any proxied bean, taking the method arguments as a key.

Little known but easy to stumble upon [2] is an implementation (design?) quirk which expects method arguments to generate unique hash codes, ignoring the Java convention of the equals() method behavior. Hence, method arguments computing the same hash code will map to the same cache entry regardless whether they equal() or not.

Update 2011-11-08 Here is an example (stripped down to essentials, use your imagination for getters, constructors, sensible null-checks etc):

class Customer{
    int id;
    int hashcode(){
        return id % 10;
    }
 
    boolean equals(Object o){
        return ((Customer)o.id) == id;
    }
}
 
class ReceiptDAOImpl implements ReceiptDAO{
    @Cacheable
    List getReceiptsForCustomer(Customer c){
    // do some database queries and get a list or receipts
   }
}
 
class TestCollision{
@Test
void testCollision(){
     Customer c1 = new Customer(1);
     Customer c2 = new Customer(11);
     List receipts1 = dao.getReceiptsForCustomer(c1);
     List receipts2 = dao.getReceiptsForCustomer(c2);
     assertTrue(receipts1 != receipts2); // fails because dao returns the same cached list
}
}

Resources

[1] Ehcache Spring Annotations on Google Code
http://code.google.com/p/ehcache-spring-annotations/

[2] Hash collision with Ehcache  Spring Annotations
http://code.google.com/p/ehcache-spring-annotations/issues/detail?id=90&can=1

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s