Be Careful With Cache Managers

If you are using spring and JPA, it is very likely that you utilize ehcache (or another cache provider). And you do that in two separate scenarios: JPA 2nd level cache and spring method caching.

When you configure your application, you normally set the 2nd level cache provider of your JPA provider (hibernate, in my case) and you also configure spring with the “cache” namespace. Everything looks OK and you continue with the project. But there’s a caveat. If you follow the most straightforward way, you get two separate cache managers which load the same cache configuration file. This is not bad per-se, but it is something to think about – do you really need two cache manager and the problems that may arise from this?

Probably you don’t. So you have to get rid of the redundant manager. To do that, you need to set your spring cache manager as shared:

<bean id="ehCacheManager"
    class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    <property name="shared" value="true" />
</bean>

This means that spring won’t create a new instance of cache manager, but will reuse the one already created by hibernate. Now, there’s something to think about here – it would depend on the order of bean creation – whether the JPA factory bean or the cache manager factory bean will be first. Luckily, this doesn’t matter for the end result, because SingletonEhCacheRegionFactory reuses an existing cache manager instance if it finds one.

So, now you have made your cache manager jvm-singleton. But then there’s another problem that you may encounter if you have multiple applications deployed and you are using JMX. The Cache manager registers itself as a JMX bean. But when you have singletons, multiple applications will try to register the same cache manager multiple times, and that will fail. The result will be a couple of exceptions in the log and the inability to control the cache manager of multiple modules. A side effect of the same problem gets in the way if you use something like Terracotta (there cache manager identity matters). Luckily, you have an easy fix for that. Just add one property to the bean definition shown above:

    <property name="cacheManagerName" value="${module.name}" />

${module.name} is a property resolved with a PropertyPlaceholderConfigurer and is configurable per webapp, so each webapp can have a different module name. That way the cache manager will be accessible under the specified name via JMX.

Overall, be careful with your cache managers. Even in case you are using different cache, jpa and DI provider, you should verify the scenarios described above.


Czech translation (by Alex Borlan from autip.com).

If you are using spring and JPA, it is very likely that you utilize ehcache (or another cache provider). And you do that in two separate scenarios: JPA 2nd level cache and spring method caching.

When you configure your application, you normally set the 2nd level cache provider of your JPA provider (hibernate, in my case) and you also configure spring with the “cache” namespace. Everything looks OK and you continue with the project. But there’s a caveat. If you follow the most straightforward way, you get two separate cache managers which load the same cache configuration file. This is not bad per-se, but it is something to think about – do you really need two cache manager and the problems that may arise from this?

Probably you don’t. So you have to get rid of the redundant manager. To do that, you need to set your spring cache manager as shared:

<bean id="ehCacheManager"
    class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    <property name="shared" value="true" />
</bean>

This means that spring won’t create a new instance of cache manager, but will reuse the one already created by hibernate. Now, there’s something to think about here – it would depend on the order of bean creation – whether the JPA factory bean or the cache manager factory bean will be first. Luckily, this doesn’t matter for the end result, because SingletonEhCacheRegionFactory reuses an existing cache manager instance if it finds one.

So, now you have made your cache manager jvm-singleton. But then there’s another problem that you may encounter if you have multiple applications deployed and you are using JMX. The Cache manager registers itself as a JMX bean. But when you have singletons, multiple applications will try to register the same cache manager multiple times, and that will fail. The result will be a couple of exceptions in the log and the inability to control the cache manager of multiple modules. A side effect of the same problem gets in the way if you use something like Terracotta (there cache manager identity matters). Luckily, you have an easy fix for that. Just add one property to the bean definition shown above:

    <property name="cacheManagerName" value="${module.name}" />

${module.name} is a property resolved with a PropertyPlaceholderConfigurer and is configurable per webapp, so each webapp can have a different module name. That way the cache manager will be accessible under the specified name via JMX.

Overall, be careful with your cache managers. Even in case you are using different cache, jpa and DI provider, you should verify the scenarios described above.


Czech translation (by Alex Borlan from autip.com).