31 July, 2011

How to register Infinispan listeners in Spring when using Infinispan as 2LC for Hibernate

In this post I will show how to register Infinispan listeners in Spring when Infinispan is used as second level cache (2LC) for Hibernate. So let’s start:
  1. Annotate your entity classes as cacheable. Pay attention to the cache region name ("cache_name") specified in the region attribute of Cache annotation.
    @Entity
    @Cache(region = "cache_name", usage = CacheConcurrencyStrategy.TRANSACTIONAL)
    @Cacheable
    @Table(name = "ENTITY_TABLE")
    public class MyEntity implements Serializable {
        // entity fields
    }
    
  2. Write your custom InfinispanRegionFactory as it is shown below. It extends from Hibernate InfinispanRegionFactory and its logic is very simple. The only thing which it does is to register listeners after its start. Pay attention to the named cache ("cache_name") to which listeners are registered. It should be the same as the cache region name used by your entities.
    public class CustomInfinispanRegionFactory extends InfinispanRegionFactory {
        private Set<Object> listeners;
    
        public CustomInfinispanRegionFactory() {
        }
    
        public CustomInfinispanRegionFactory(Properties props) {
            super(props);
        }
    
        public void setListeners(Set<Object> listeners) {
            this.listeners = listeners;
        }
    
        @Override
        public void start(Settings settings, Properties properties) throws CacheException {
            super.start(settings, properties);
            for(Object listener : listeners) {
                // add listener to named cache
                getCacheManager().getCache("cache_name").addListener(listener);
                // add listener to cache manager
                getCacheManager().addListener(listener);
            }
        }
    }
    
  3. Write your cache Listener. You can find more information about Infinispan listeners here.
    @Listener
    public class TestCacheListener {
        @CacheStarted
        public void cacheStarted(Event event) {
              System.out.println("Cache started. Details = " + event);
        }
    
        @CacheStopped
        public void cacheStopped(Event event) {
              System.out.println("Cache stopped. Details = " + event);
        }
    
        @CacheEntryCreated
        @CacheEntryModified
        @CacheEntryRemoved
        public void handle(Event event) {
            System.out.println("Cache entry modified. Details = " + event);
        }
    }
    
  4. Configure Hibernate and Infinispan in Spring. Register your listener. You can find more information about using Infinispan as 2LC in Hibernate here.
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
            <property name="packagesToScan" value="org.zmeu.blog.persistence.entity" />
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.cache.use_second_level_cache">true</prop>
                    <prop key="hibernate.cache.infinispan.cfg">cache-config.xml</prop>
                </props>
            </property>
            <property name="cacheRegionFactory" ref="cacheRegionFactory"/>
    </bean>
    
    <bean id="cacheRegionFactory" class="com.xtrader.persistence.cache.CustomInfinispanRegionFactory">
        <property name="listeners">
            <set>
                <ref bean="listener"/>
            </set>
        </property>
    </bean>
    
    <bean id="listener" class="org.zmeu.blog.persistence.cache.TestCacheListener"/>
    
  5. Define the named cache ("cache_name") inside Infinispan configuration cache (cache-config.xml).
    <namedCache name="cache_name">
        <!--  named cache configurations -->
    </namedCache>
    
  6. You are done!
For this example I used: Spring 3.0.5, Hibernate 3.6.5 and Infinispan 4.2.1.

No comments:

Post a Comment