Hibernate Second Level Cache, JBoss Cache and JBoss AS 5.1 in default configuration

I've recently tried to set up JBoss Cache as a hibernate second level cache provider in Seam 2 application deployed in default configuration on JBoss AS 5.1. I also wanted to use Seam CacheProvider functionality. I've already used JBoss Cache with success in clustered environment, which used copy of all configuration.

However this time using copy-paste technique didn't worked well. In all configuration I just had to add following properties to persistence.xml:
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.jbc2.JndiMultiplexedJBossCacheRegionFactory" />
   <property name="hibernate.cache.region.jbc2.cachefactory" value="java:CacheManager" />
   <property name="hibernate.cache.region.jbc2.cfg.entity" value="mvcc-entity" />
   <property name="hibernate.cache.region.jbc2.cfg.collection" value="mvcc-entity" />

If we do this in default configuration we get then following exception:
java.lang.ClassNotFoundException: org.hibernate.cache.jbc2.JndiMultiplexedJBossCacheRegionFactory.

It turns out that in default configuration, we have to copy three jars from all configuration lib directory: hibernate-jbosscache2.jar, jbosscache-core.jar, jgroups.jar. If you are working with project generated in seam-gen, you can add this jars to deployed-jars-ear.list. There is also no instance of org.jboss.ha.cachemanager.CacheManager boud to java:CacheManager jndi name. There are to ways of solving this problem. First is to copy necessary things from all configuration (i.e. cluster catalog where cacheManager is initiated). Second approach is to use other region_factory in hibernate config. I used second option, because application I'm working on, will be deployed on single server. Looking into documentation leaves two options for non jndi region_factory:
  • org.hibernate.cache.jbc2.SharedJBossCacheRegionFactory - one cache instance for entities, collections, queries, timestamps
  • org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory - separate cache instances for entities, collections, queries, timestamps

I used SharedJBossCacheRegionFactory for simplicity. We have to provide path to cache configuration file (hibernate.cache.region.jbc2.cfg.shared property). Samples of such files are available in jboss cache distribution. Working persistence.xml file in default configuration:
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.region_prefix" value="hibernate-cache"/>
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.jbc2.SharedJBossCacheRegionFactory" />
<property name="hibernate.cache.region.jbc2.cfg.shared" value="META-INF/hibernate-jboss-cache.xml"/>

Last thing is setting up cache provider for seam in components.xml:
<cache:jboss-cache2-provider name="defaultCache" auto-create="true" configuration="META-INF/dcache.xml" />

Sample usage of cache provider for such configuration:
@In(value = "defaultCache")
    protected CacheProvider cacheProvider;

    private Object getSimpleDictionariesByType(SimpleDictionaryType type) {
        String cacheKey = "SimpleDictionaryType." + type;
        Object value = cacheProvider.get("dictionaryCache", cacheKey);

        if (value == null) {
                ...

Stanisław Ogórkis

Software engineer specializing in delivering highly interactive web applications and complex enterprise systems.

1 comments: