I have created a spring boot application and implemented EhCache in the maven project. My xml configuration file for EhCache is as follows :
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir" />
<cache name="labCabSourceInfoCache"
maxEntriesLocalHeap="10000"
maxEntriesLocalDisk="1000"
eternal="false"
diskSpoolBufferSizeMB="20"
timeToIdleSeconds="300" timeToLiveSeconds="300"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<persistence strategy="localTempSwap" />
</cache>
I have set expiry time as 300 in the parameters timeToIdleSeconds & timeToLiveSeconds
But it doesn't works for me. I didn't used any configuration bean for the cache implementaion. I uses #Cacheable annotation for the method which is meant to be used cache.
#Cacheable(value="labCabSourceInfoCache", key="#labAlias.concat(#Account)")
public String findLabCabSourceInfo(String labAlias, String Account) {
try {
//codes return "some string"
} catch (Exception e) { } return null;
}
Why it is not evicted or cleared?
You may need to enable the processing of the caching annotations.
Can you try adding #EnableCaching on your main class.
From the tutorial
https://spring.io/guides/gs/caching/
The #EnableCaching annotation triggers a post processor that inspects
every Spring bean for the presence of caching annotations on public
methods. If such an annotation is found, a proxy is automatically
created to intercept the method call and handle the caching behavior
accordingly.
Also you can add the following code in and then analyse thorough Jconsole, the details of the caches created in your application.
#Bean(initMethod="init")
#Autowired
public ManagementService managementService(CacheManager cacheManager,
MBeanServer mBeanServer) {
return new ManagementService(cacheManager, mBeanServer, true, true,true, true);
}
Related
I'm integrating Caching into my web application but for some reason Application Context failed to load when adding the #Cacheable annotation.
I have been trying to solve the issue for two days now, your help is really appreciated!
app.context.xml
<cache:annotation-driven cache-manager="EhCacheManagerBean" key-generator="customKeyGenerator" />
<bean id="EhCacheManagerBean" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcacheBean" />
<bean id="ehcacheBean" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:configLocation="classpath:EhCache.xml" p:shared="true" />
<bean id ="customKeyGenerator" class="com.app.site.v2.cache.customKeyGenerator"/>
<bean id="siteService" class="com.app.site.v2.SiteService" primary="true"/>
EhCache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir" />
<cache name="cacheSite"
maxEntriesLocalHeap="100"
maxEntriesLocalDisk="1000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<persistence strategy="localTempSwap" />
</cache>
Method that is being cached
public class SiteService implements ISiteService {
#Cacheable("cacheSite")
public JsonObject getSiteJson(String siteId, boolean istTranslated) { ... }
}
Exception that is being thrown
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'siteService' is expected to be of type 'com.app.site.v2.SiteService' but was actually of type 'com.sun.proxy.$Proxy57'
The comment of #yegdom is actually the right answer. When adding the Cacheable annotation, Spring generates a proxy which implements ISiteService. And somewhere in your code, you have a bean requiring SiteService, the implementation.
There are three solutions (in preference order):
Remove the useless interface... A single implementation is just adding complexity for no direct benefit. Removing it will force Spring to use a class proxy
Fix your dependency to use ISiteService
Add proxy-target-class="true" to cache:annotation-driven to tell Spring to create a class proxy
I really do not recommend the last one since you should always depend on the interface or always depend on the class (and delete the interface). Not both at the same time.
I use ehcache in a webapp whose versions are deployed in parallel on a Tomcat instance. This is a handy way to deploy new versions without stopping an application.
I however have a problem with this way to proceed : even if I give the cache and disk store different names, depending on the versions of the webapp, all caches are stopped when stopping one instance.
My config is :
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd" name="mywebapp-${project.version}_build_${buildNumber}">
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000"
eternal="false"
timeToLiveSeconds="300"
timeToIdleSeconds="300"
overflowToDisk="true"
diskPersistent="false"
memoryStoreEvictionPolicy="LRU"
statistics="true"
/>
<cache
maxElementsInMemory="1000"
maxElementsOnDisk="10000"
name="org.hibernate.cache.internal.StandardQueryCache"
eternal="false"
timeToLiveSeconds="300"
timeToIdleSeconds="300"
overflowToDisk="true"
diskPersistent="false"
statistics="true"/>
<cache
name="org.hibernate.cache.spi.UpdateTimestampsCache"
maxElementsInMemory="10000"
maxElementsOnDisk="100000"
timeToLiveSeconds="300"
timeToIdleSeconds="300"
eternal="false"
overflowToDisk="true"
diskPersistent="false"
statistics="true"/>
<cache
name="query.Presences"
maxElementsInMemory="100"
maxElementsOnDisk="1000"
eternal="false"
timeToLiveSeconds="300"
timeToIdleSeconds="300"
overflowToDisk="true"
diskPersistent="false"
statistics="true"/>
<diskStore path="java.io.tmpdir/mywebapp-${project.version}_build_${buildNumber}"/>
</ehcache>
${project.version} and ${buildNumber}
being replaced by maven during the build process.
Does someone know how to avoid this unwanted behaviour ?
I am using ehcache-core-2.4.3 and hibernate-ehcache-4.3.8.
The way net.sf.ehcache.constructs.web.ShutdownListener works is by shutting down ALL cache managers.
So the only way for this to work for you is by making sure your cache managers end up in different class loaders, that is ehcache is loaded by the web application class loader and not the container one.
Do you provide ehcache jar in your app's WEB-INF/lib? If yes, are you sure there is not an Ehcache in tomcat's classpath?
If this solution still does not work, you may be better off creating your own ServletContextListener that would shutdown only the cache manager from the containing application.
Some details are missing from your query.
1)How are you stopping the cache?
2)How are you deploying application in tomcat?
3)Have you checked the location where does the cache object is created ?
But as a behavior all cache will cleared once you restart tomcat.
I have an application in which I use spring 3.0.2 and ibatis. Now, I need to integrate ehcache with my code. I tried this link but couldnt get it working. I would prefer someone to give me the details of the jars required, xml configurations to be done and code changes if required.
Upgrade to the latest spring 3.1 milestone - it has built-in cache support through annotations - see here
Apart from that, you can always use the EhCacheFactoryBean
To implement this in your application, follow these steps:
Step 1:
Add the jars to your application as listed on the Ehcache Annotations for Spring project site.
Step 2:
Add the Annotation to methods you would like to cache. Lets assume you are using the Dog getDog(String name) method from above:
#Cacheable(name="getDog")
Dog getDog(String name)
{
....
}
Step 3:
Configure Spring. You must add the following to your Spring configuration file in the beans declaration section:
<ehcache:annotation-driven cache-manager="ehCacheManager" />
Please refer to Ehcache site for complete details.
To integrate Ehcache just follow below steps
1 - Add Dependency in pom XML file
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.9</version>
</dependency>
2 - create an xml file called spring-cache.xml put it in the resources folder
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p" xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<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="classpath:ehcache.xml" />
</bean>
</beans>
3 - as you can see we are using reference of ehcache.xml so create file and put it in resources folder
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="true"
monitoring="autodetect" dynamicConfig="true">
<cache name="users" maxEntriesLocalHeap="5000"
maxEntriesLocalDisk="1000" eternal="false" diskSpoolBufferSizeMB="20"
timeToIdleSeconds="200" timeToLiveSeconds="500"
memoryStoreEvictionPolicy="LFU" transactionalMode="off">
<persistence strategy="localTempSwap" />
</cache>
</ehcache>
so can see create a cache for "users" so that can use wherever user list is queried from the database
4 - use it like below code
#Cacheable(value="users")
public List<User> userList() {
return userDao.findAll();
}
so that's it the same way you can implement cache wherever is required
still have some doubt or confusion see live demo
Integrate EhCache in Spring MVC
I have a problem where net.sf.ehcache.CacheManager appears returns invalid statistics.
I'm using ehcache-core v2.3.2 (latest version) with ehcache-spring-annotations.
The problem is that getMemoryStoreObjectCount returns 1 object while both getCacheHits and getCacheMisses returns 0. Isn't the total count supposed to be hits + misses ?
The unit test below should illustrate the problem (it's applied to an empty database):
#Test
public void testCache() {
Entity e = ..
dao.storeEntity(e);
dao.getEntity(e);
assertEquals(1, cache.getStatistics().getMemoryStoreObjectCount()); // ok
assertEquals(0, cache.getStatistics().getCacheHits()); // ok
assertEquals(1, cache.getStatistics().getCacheMisses()); // fails due to 0
}
For completeness I include all essential configuration:
Spring config
<ehcache:annotation-driven cache-manager="ehCacheManager" />
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
</bean>
ehcache.xml
<ehcache>
<defaultCache eternal="false" maxElementsInMemory="1000"
overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0"
timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>
</ehcache>
dao
#Cacheable(keyGenerator=#KeyGenerator(name="StringCacheKeyGenerator"))
public Entity getEntity(Serializable key) {
return // sql ...
}
Add statistics="true" to your ehcache.xml, it's usually better to keep your configuration changes outside your code.
<ehcache>
<defaultCache ... statistics="true" />
...
</ehcache>
Found the solution to the problem by setting the following properties in net.sf.ehcache.hibernate.EhCache:
cache.setStatisticsEnabled(true);
cache.setStatisticsAccuracy(Statistics.STATISTICS_ACCURACY_GUARANTEED);
The <defaultCache ... statistics="true" /> works greatly
in contrast with the old way cache.setStatisticsEnabled(true); that needs the lower version of ehcache (core and etc).
Hi I've run into some problems with hibernate 2nd level cache.
As cache provider I use ehcache.
Part of config from persistence.xml
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.EhCacheProvider" />
<property name="hibernate.cache.provider_configuration_file_resource_path" value="/ehcache.xml" />
I configure my entities using annotations so:
#Cache(region = "Kierunek", usage = CacheConcurrencyStrategy.READ_WRITE)
public class Kierunek implements Serializable {
imports for those annotations are:
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
my ehcache.xml
<diskStore path="java.io.tmpdir" />
<defaultCache maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
diskPersistent="false" diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU" />
<cache name="Kierunek" maxElementsInMemory="1000"
eternal="true" overflowToDisk="false" memoryStoreEvictionPolicy="LRU" />
And anyone idea why i get following error ?
WARNING: Could not find a specific ehcache configuration for cache named [persistence.unit:unitName=pz2EAR.ear/pz2EJB.jar#pz2EJB.Kierunek]; using defaults.
19:52:57,313 ERROR [AbstractKernelController] Error installing to Start: name=persistence.unit:unitName=pz2EAR.ear/pz2EJB.jar#pz2EJB state=Create
java.lang.IllegalArgumentException: Cache name cannot contain '/' characters.
solution is to add another property to persistence.xml
<property name="hibernate.cache.region_prefix" value=""/>
and that removes that faulty prefix big thx ruslan!
IMHO, you get the generated region name for your class. This generated name "persistence.unit:unitName=pz2EAR.ear/pz2EJB.jar#pz2EJB.pl.bdsdev.seps.encje.Kierunek". And it's not defined in your's ehcache.xml configuration. Also it's looking for the predefined name, so it can't use default region.
As an option to solve this problem you can use #Cache annotation properties to predefine some region name, like
#Cache(region = 'Kierunek', usage = CacheConcurrencyStrategy.READ_WRITE)
public class Kierunek implements Serializable {
// ....
}
And in ehcache.xml
<cache name="Kierunek"
maxElementsInMemory="1000"
eternal="true"
overflowToDisk="false"
memoryStoreEvictionPolicy="LRU" />
Hibernate add prefix to cache names based on appname or value of property hibernate.cache.region_prefix
If You set this property for "" (empty string) then You have regions named exactly like name in hibernate config.
EHCache needs a configuration that tells it how to cache the objects in your application (live time, cache type, cache size, caching behaviour etc). For every class you try to cache it will try to find an appropriate cache configuration and print the error above if it fails to do so.
See http://ehcache.sourceforge.net/documentation/configuration.html for how to configure EHCache.