I want to do something with ehcache in Java that I think should be extremely simple, but I\'ve spent enough time frustrating myself with the docs...
Write a
After spending some quality time with the debugger, I believe I have an answer for the OP.
The issue (at least from what I have seen) centers around the non-clustered disk cache files and how they get read back in. In the file net.sf.ehcache.store.compound.factories.DiskPersistentStorageFactory.java, the method:
public DiskPersistentStorageFactory(Ehcache cache, String diskPath) {
super(getDataFile(diskPath, cache), cache.getCacheConfiguration().getDiskExpiryThreadIntervalSeconds(),
cache.getCacheConfiguration().getDiskSpoolBufferSizeMB(), cache.getCacheEventNotificationService(), false);
indexFile = new File(getDataFile().getParentFile(), getIndexFileName(cache));
flushTask = new IndexWriteTask(indexFile, cache.getCacheConfiguration().isClearOnFlush());
if (!getDataFile().exists() || (getDataFile().length() == 0)) {
LOG.debug("Matching data file missing (or empty) for index file. Deleting index file " + indexFile);
indexFile.delete();
} else if (getDataFile().exists() && indexFile.exists()) {
if (getDataFile().lastModified() > (indexFile.lastModified() + TimeUnit.SECONDS.toMillis(1))) {
LOG.warn("The index for data file {} is out of date, probably due to an unclean shutdown. "
+ "Deleting index file {}", getDataFile(), indexFile);
indexFile.delete();
}
}
diskCapacity = cache.getCacheConfiguration().getMaxElementsOnDisk();
memoryCapacity = cache.getCacheConfiguration().getMaxElementsInMemory();
memoryPolicy = determineEvictionPolicy(cache.getCacheConfiguration());
}
checks the timestamps on the data files. The problem I am seeing is that no matter how I end up shutting down the cache/manager, the files are never get synchronized properly. My quick and dirty workaround was to adjust the time of the data file to be just past the timestamp on the index file:
File index = new File( path, name + ".index" );
File data = new File( path, name + ".data" );
data.setLastModified( index.lastModified() + 1 );
Granted, this is not elegant, but it serves my needs, as our project uses clustered caches, and this allows me to debug standalone with a persistent cache...and without having to actually run Terracotta locally.
One caveat is that for non-clustered caches, I do have to flush() after every put() and remove() in order to keep the disk image fresh, especially when debugging due to the lack of shutdown support when you just "pull the plug".
I had and resolved a similar issue.
I want to configure ehcache to have a given cache persisting elements on disk.
But I want to do it only in local environment (production environment works with a distributed
persistence) so I switch the configuration programmatically when the application starts (a web application in my case)
File configurationFile = new File(event.getServletContext().getRealPath(EHCACHE_CONFIG_PATH));
Configuration configuration = ConfigurationFactory.parseConfiguration(configurationFile);
//...doing other stuff here...
CacheConfiguration cacheConfiguration = configuration.getCacheConfigurations().get("mycachename");
if(localEnvironment){
cacheConfiguration.addPersistence(new PersistenceConfiguration().strategy(Strategy.DISTRIBUTED));
}else{
//siteCacheConfiguration.addPersistence(new PersistenceConfiguration().strategy(Strategy.LOCALRESTARTABLE));
//deprecated lines..
siteCacheConfiguration.setDiskPersistent(true);
siteCacheConfiguration.setOverflowToDisk(true);
}
I had problem with the commented line siteCacheConfiguration.addPersistence(new PersistenceConfiguration().strategy(Strategy.LOCALRESTARTABLE))
, in fact Ehcache code (I'm using ehcache-2.6.11
) throws an Exception if you use Strategy.LOCALRESTARTABLE
without an enterprise version of the jar:
CacheException: You must use an enterprise version of Ehcache to successfully enable enterprise persistence.
Digging into the code I realized that these two (deprecated) lines do the same eluding the entreprise version Exception
siteCacheConfiguration.setDiskPersistent(true);
siteCacheConfiguration.setOverflowToDisk(true);
Remember to add CacheManager.getInstance().shutdown()
on the shutdown of the application!
Hope this helps.