I want to distribute my EhCache via a JMS Topic. This is documented here on EhCache's site
I'm using:
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?
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=";"
/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With