views:

785

answers:

2

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?

+3  A: 

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=";"
    />
MikeHoss
A: 

Regarding the key generation issue, it's actually a known problem - MOD-255. We are going to be patching that into the Spring Modules Fork shortly.

Antony Stubbs