Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding JMS Info breaks EhCache

I want to distribute my EhCache via a JMS Topic. This is documented here on EhCache's site

I'm using:

  • ehcache-1.6.0-beta3
  • ehcache-jmsreplication-0.3
  • spring-2.5
  • spring-modules-0.9

My Spring config looks like this:

<bean id="cacheManager"
      class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
</bean>  
<bean id="cacheProvider"
      class="org.springmodules.cache.provider.ehcache.EhCacheFacade">
  <property name="cacheManager" ref="cacheManager" />
</bean>    
<ehcache:proxy id="pocDaoCache" refId="pocDao">
    <ehcache:caching methodName="fetch" cacheName="pocCache" />
</ehcache:proxy>

And, pre-JMS config, my ehcache.xml looks like this:

 <diskStore path="c:/projects/cache/demo" />

  <defaultCache maxElementsInMemory="50" eternal="false"
  timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" />


 <cache name="pocCache"
        maxElementsInMemory="10000"
        maxElementsOnDisk="1000"
        eternal="false"
        overflowToDisk="true"
        diskSpoolBufferSizeMB="20"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        memoryStoreEvictionPolicy="LFU"
        / >

And this works fine. So I add my Topic information:

 <cacheManagerPeerProviderFactory
             class="net.sf.ehcache.distribution.jms.JMSCacheManagerPeerProviderFactory"
             properties="initialContextFactoryName=JmsInitialContextFactory,
      userName=myuser,password=mypass,
                 providerURL=tcp://jmsdev1-jndi,tcp://jmsdev2-jndi
                 topicConnectionFactoryBindingName=TCF-00,
                 topicBindingName=MyTopiceName"
             propertySeparator=","
             />

And I get a NullPointer when I get an application context. Here is the stack trace:

   org.springframework.beans.factory.BeanCreationException:  
org.springframework.beans.factory.BeanCreationException: Error creating bean 
with name 'cacheManager' defined in class path resource [cache-context.xml]: 
Invocation of init method failed; nested exception is java.lang.NullPointerException
         at org.springframework.beans.factory.support.AbstractAutowireCapableBean
 Factory.initializeBean(AbstractAutowireCapableBeanFactory.java:1336)
         at org.springframework.beans.factory.support.AbstractAutowireCapableBean
 Factory.doCreateBean(AbstractAutowireCapableBeanFactory.java:471)
         at org.springframework.beans.factory.support.AbstractAutowireCapableBean
 Factory$1.run(AbstractAutowireCapableBeanFactory.java:409)
         at java.security.AccessController.doPrivileged(Native Method)
         at org.springframework.beans.factory.support.AbstractAutowireCapableBean
 Factory.createBean(AbstractAutowireCapableBeanFactory.java:380)
         at org.springframework.beans.factory.support.AbstractBeanFactory$1.getOb
 ject(AbstractBeanFactory.java:264)
         at org.springframework.beans.factory.support.DefaultSingletonBeanRegistr
 y.getSingleton(DefaultSingletonBeanRegistry.java:217)
  [snip]

Any ideas from anyone?

like image 521
MikeHoss Avatar asked Mar 20 '09 15:03

MikeHoss


1 Answers

The real problem is that Ehcache's documentation isn't right -- not even close -- to how it is really implemented. Through logging and looking through the code in the jmsreplication module, I was able to get it working.

 <cacheManagerPeerProviderFactory
        class="net.sf.ehcache.distribution.jms.JMSCacheManagerPeerProviderFactory"
        properties="initialContextFactoryName=com.InitialContextFactory;

    userName=uname;password=passwd;
            replicationTopicConnectionFactoryBindingName=TCF;
            replicationTopicBindingName=CACHE;
    providerURL=tcp://server1:7222,tcp://server2:7222;
    getQueueConnectionFactoryBindingName=QCF;
    getQueueBindingName=CACHE_LOAD
    "
    propertySeparator=";"
    />

Another thing that tripped me up was simple, once I realized it -- you have to implement your own key generator to ensure that Ehcache saves the objects with the same keys on each JVM. That makes perfect sense, when you think about it.

Yes, you have to put in the loader queue information into the cacheManagerPeerProviderFactory. That is because, if you start up a process after one has been running, the new process can pre-load the cache from the existing process.

You configure the loader requester (cacheLoaderFactory) with the exact same settings:

   <cacheLoaderFactory
        class="net.sf.ehcache.distribution.jms.JMSCacheLoaderFactory"
   properties="initialContextFactoryName=com.InitialContextFactory;

    userName=uname;password=passwd;
            replicationTopicConnectionFactoryBindingName=TCF;
            replicationTopicBindingName=CACHE;
    providerURL=tcp://server1:7222,tcp://server2:7222;
    getQueueConnectionFactoryBindingName=QCF;
    getQueueBindingName=CACHE_LOAD
    "
    propertySeparator=";"
    />
like image 131
MikeHoss Avatar answered Sep 23 '22 06:09

MikeHoss