2 Replies Latest reply on Feb 25, 2011 9:04 AM by alexmak

    Sharing Infinispan Cache with multiple Hibernate SessionFactories

    alexmak

      Hi!

       

      I have a system, that consists of several applications. All applications use the same hibernate entities.

      Applications can be deployed as separate web applications on the same server.

       

      I want to use infinispan as second-level-cache for hibernate, and I want to share it across applications deployed on the same server.

       

      I already tried following setup.

       

      ConnectionPool and Infinispan CacheManager defined in Jetty 6.1.26 and bound to JNDI context

      Hibernate is configured with org.hibernate.cache.infinispan.JndiInfinispanRegionFactory

       

      I have two webapps deployed on the same server. Thay are successfully obtaining the cache instance from JndiInfinispanRegionFactory.

       

      In JMX console I see that only one instance of cache is created, so everithing is okay.

       

      Then I try to load entity with session.get() from 1-st  web app. As expected - entity is not in cache, hibernate hits Database.

      Entity is put into the cache. JMX shows that cache contains 1 entry.

       

      Then I try to load the same entity from 2-nd web app. Hibernates hits the cache - and cannot find the entry!

      (however I can see this entry when I set brake point at org.hibernate.cache.infinispan.util.CacheAdapterImpl.get() )

      It loads second copy from database and puts it to the cache. Now cache contains two entries for the same object.

       

      Entity in hibernate is defined with CacheConcurrencyStrategy.READ_ONLY.

      It looks like waste of memory to have several copies of objects in the same cache instance.

       

      What is the strategy infinispan use to resolve objects in cache?

      How can I setup infinispan/hibernate to share cache between sessionFactories?

       

      Any ideas?

        • 1. Sharing Infinispan Cache with multiple Hibernate SessionFactories
          galder.zamarreno

          First of all, the JNDI region factory is so that multiple apps can benefit from a single cache manager, and hence a single JGroups channel. That way, if you have N apps, you don't need to maintain N cache managers and N JGroups channels, because for each JGroups channels you have to figure out different multicast address...etc.

           

          However, what you seem to be trying is to have two separate Hibernate SessionFactories share the caches which is a different thing. I don't know how to do that and probably it's not a good idea, because each app could be deploying different versions of the same entities, even if the class names are the same.

           

          I suspect that what you want is for different apps to share the same Hibernate session factory but you'd have to check with the Hibernate people on how to do that.

          1 of 1 people found this helpful
          • 2. Re: Sharing Infinispan Cache with multiple Hibernate SessionFactories
            alexmak

            Galder,

            thanks for reply!

             

            I have found the reason for such behavior. And it has nothing to do with Infinispan.

             

            In fact it turned out to be the fundamental feature of app server – different classloaders for different applications.

             

            Hibernate’s org.hibernate.cache.CacheKey.equals() method returns false for CacheKey classes loaded from different classloaders.

             

            Moving all Hibernate jars to Jetty lib/ext folder and removing them from web applications have resolved the classloader limitation.

            And now applications can share the entities the way I need.

             

            By the way, I found next posible solutions so far:

             

            1. Moving all Hibernate libraries to application server classloader.
            2. Patching and replacement of original Hibernate's CacheKey class.
            3. Using Aspectj to create around advice over the equals method, and write classloader-agnostic implementation.
            1 of 1 people found this helpful