I have a simple one class test to load ehache 2.8.1
Everything is fine however if setting either diskPersistent="true" or overflowToDisk="true" then the VM never terminates.
I have tried setting the shutdown hook but this isn't fired as the thread used by Ehcache isn't a daemon so the vm never gets that far.
<ehcache
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<diskStore path="/temp"/>
<defaultCache
maxElementsInMemory="100"
eternal="false"
overflowToDisk="false"
/>
<cache
name="resolveIpAddresses"
maxElementsInMemory="100000"
diskPersistent="true"
overflowToDisk="true"
eternal="false"
timeToLiveSeconds="3600"
/>
</ehcache>
The ehcache is being managed by a spring 3.1.8 container with the beans
<cache:annotation-driven />
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cacheManager-ref="ehcache"/>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="/ehcache.xml" p:shared="true"/>
Changing the disk settings to false works fine but obviously not great. How do I tell ehcache that the disk threads are daemon?
If you are using a servlet container, you can use the servlet ShutdownListener, otherwise it's possible to shutdown the disk threads by calling CacheManager.getInstance().shutdown() explicitly in the code.
The Ehcache documentation says that the JVM shutdown hook will:
shutdown the DiskStore. If the DiskStore is persistent, it will write the entries and index > to disk.
The shutdown hook can be explicitly called with a call to System.exit(), in addition to being called when the last non-daemon thread shutdown.
Related
I have a tomcat server with ehcache. And I have a second tomcat with servlet. When second servlet is inited it should take ehcache from #1 and put all data to its cache.
Is there built-in mechanism such "on start replication" in ehcache? Or how can I get serialized ehcache data and then de-serialize them to ehcache. I understand that I can read all keys one by one and then all their values then serialize but maybe there's a better way?
Thanks
There is no out of the box support for what you are asking.
Alternatives are:
Ehcache clustering with Terracotta
Ehcache replication
Note that a major difference between the two is that the second option offers NO guarantees with regards to data consistency between the two Ehcache instances.
Disclaimer: I work for Terracotta on Ehcache
Here's my solution using built-in rmi replication solution:
Master config:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=localhost, port=40001,
socketTimeoutMillis=2000"/>
<cache name="masterCache"
maxEntriesLocalHeap="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=true, replicatePuts=false, replicateUpdates=false,
replicateUpdatesViaCopy=false, replicateRemovals=false "/>
<persistence strategy="none"/>
</cache>
Here I turn on RMI listener for slaves and enable RMI for cache but without any replication because I just need data on slave when it starts and that's all
Slave config:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//localhost:40001/masterCache"/>
<cache name="masterCache"
maxEntriesLocalHeap="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<bootstrapCacheLoaderFactory class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
properties="bootstrapAsynchronously=false"/>
<persistence strategy="none"/>
</cache>
I made RMI connection to master node and turn on cache's bootstrap.
I am working with ehcache. I am caching Spring #Service method :
#Service( value = "dataServicesManager" )
#Transactional
public class DataServicesManager implements IDataServicesManager{
#Autowired
private IDataDAO dataDAO;
#Override
#Cacheable( value = "alldatas" )
public List<Data> getAllDatas(Integer param) {
// my logic
return results;
}
// others services
}
Here is the Spring configuration snippet:
<cache:annotation-driven/>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="ehcache"/>
</bean>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="WEB-INF/ehcache.xml"/>
<property name="shared" value="true"/>
</bean>
Here is my ehcache configuration.
<ehcache xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect" dynamicConfig="true">
<diskStore path="C:/TEMP/ehcache"/>
<defaultCache eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="1200"
overflowToDisk="true"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120" />
<cache name="alldatas" maxEntriesLocalHeap="10000" eternal="false"
timeToIdleSeconds="21600" timeToLiveSeconds="21600" memoryStoreEvictionPolicy="LRU">
</cache>
</ehcache>
When i call the service method getAllDatas from a Spring #Controller the method is cached and the second time call retrieve the result stores in cache.
What i don't understand is that i cannot find the <diskStore path="C:/TEMP/ehcache"/> specify in the ehcache.xml. So i have two questions :
Question 1: Why "C:/TEMP/ehcache" directory is not created ?
Question 2: Where is cached my service results ?
Your Ehcache configuration is to blame.
The defaultCache element will only be used when you create a cache programatically without specifying a configuration.
But you define explicitly your alldatas cache, without any disk options.
So your configuration needs to become:
<cache name="alldatas" maxEntriesLocalHeap="10000" eternal="false"
timeToIdleSeconds="21600" timeToLiveSeconds="21600" memoryStoreEvictionPolicy="LRU"
overflowToDisk="true"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120">
</cache>
And then this cache will use the disk store.
If you do not plan on having other caches in your application, you can also remove the defaultCache element for clarity.
Probably because your retrieved data does not overflow to disk. Caching is done in memory until some threshold is overpassed. Try to reduce the maxEntriesLocalHeap to something that you know is small enough for your data to overflow and see if the file is created.
I have configured ehcache for hibernate 2nd level cache to use a Terracotta server. Everything is working fine, except the UpdateTimestampsCache for the query cache is just not showing up in the Dev Console. We are using Hibernate 3.6.10 and ehcache 2.6.0.
I am seeing all entity, collection, query and the StandardQueryCache, but not org.hibernate.cache.UpdateTimestampsCache. I know the timestamp cache exists and is being used because I can see the stats on it using the the metrics lib instrumented in.
Any ideas?
Thanks!
Here's my ehcache.xml config
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false"
name="Hibernate-CacheManager"
monitoring="autodetect"
dynamicConfig="true">
<terracottaConfig url="localhost:9510" />
<defaultCache
eternal="false"
overflowToDisk="false"
maxElementsInMemory="50000"
timeToIdleSeconds="7200"
timeToLiveSeconds="0">
<cacheDecoratorFactory
class="com.yammer.metrics.ehcache.InstrumentedEhcacheFactory" />
<terracotta/>
</defaultCache>
<cache
name="org.hibernate.cache.UpdateTimestampsCache"
eternal="false"
overflowToDisk="false"
maxElementsInMemory="500"
timeToIdleSeconds="7200"
timeToLiveSeconds="0">
<cacheDecoratorFactory
class="com.yammer.metrics.ehcache.InstrumentedEhcacheFactory" />
<terracotta/>
</cache>
<cache
name="org.hibernate.cache.StandardQueryCache"
eternal="false"
overflowToDisk="false"
maxElementsInMemory="50000"
timeToIdleSeconds="7200"
timeToLiveSeconds="0">
<cacheDecoratorFactory
class="com.yammer.metrics.ehcache.InstrumentedEhcacheFactory" />
<terracotta/>
</cache>
</ehcache>
Recopying answer from: http://forums.terracotta.org/forums/posts/list/0/7554.page#36815
Hibernate does not maintain statistics for the UpdateTimestampsCache cache up to Hibernate 4.0.0. This explains why the cache does not show up in the terracotta dev console.
This is filed as bug https://hibernate.onjira.com/browse/HHH-5326
I'm trying to move the creation of Cache that uses RMI from ehcache.xml file to a Spring xml.
It wasn't a problem to just create a EhCacheFactoryBean but how does RMICacheReplicatorFactory definition suppose to/can be implemented?
Here is how it looks in ehcache.xml file.
Many thanks,
Idan
<cache name="MyCache1"
maxElementsInMemory="1000"
eternal="false"
overflowToDisk="true"
diskSpoolBufferSizeMB="20"
timeToLiveSeconds="3000"
timeToIdleSeconds="3000"
memoryStoreEvictionPolicy="LFU">
<!-- RMI replication listener -->
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=true,
replicatePuts=true,
replicatePutsViaCopy=true,
replicateUpdates=true,
replicateUpdatesViaCopy=true,
replicateRemovals=true" />
<!-- RMI Cache bootstrap -->
<bootstrapCacheLoaderFactory
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"
propertySeparator="," />
</cache>
When using Spring 3 there is a cacheEventListeners property of type Set<CacheEventListener> for the EhCacheFactoryBean (see https://jira.springsource.org/browse/SPR-6234). When using 2.5 you could extend EhCacheFactoryBean yourself like shown here.
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?
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=";"
/>
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.