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.
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 want to use ehcache in my spring mvc web application.because my server reset every day so i want caching be permanent. do i save it in hard path? and hoe save it?
thanks.
in my dispatcher-servlet.xml i add this
<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"/>
<property name="shared" value="true"/>
</bean>
and my ehcach.xml is
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<diskStore path="c:/tmp"/>
<defaultCache
maxElementsInMemory="500" eternal="true" overflowToDisk="false" memoryStoreEvictionPolicy="LFU"/>
<cache name="mycache"
maxElementsInMemory="0"
eternal="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="1200"
memoryStoreEvictionPolicy="LRU">
[1] <persistence strategy="localRestartable" synchronousWrites="false" />
</cache>
i add this [1] until caching be permanent and after server reset not be remove.but this exception occur Element does not allow nested elements.
also i use ehcach-core2.7.0.jar
Element <cache> does not allow nested <persistence> elements.
You should not mix legacy configuration options - attributes diskPersistent and overflowToDisk on the cache element with recommended persistence element.
However, to get to the open source disk persistent setting, you need to stick with the legacy options.
So your configuration should drop the persistence element to become:
<cache name="mycache"
maxElementsInMemory="0"
eternal="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="1200"
memoryStoreEvictionPolicy="LRU">
</cache>
However, you should also give a meaningful value to maxElementsInMemory, so you can have a hot set of entries for which you do not need to pay the deserialization price when accessing them.
You also need to decide if you want eternal elements or have expiration. For this, remove either eternal="true" or the timeToLiveSeconds and timeToIdleSeconds pair. Having both is not an error in Ehcache for compatibility reasons, but makes it hard to know what you intended initially.
And as a last advice, I would move the cache content to a folder with a more descriptive name instead of c:/tmp.
Note that the open source disk persistent tier is not fault tolerant, so improper shutdown of the Cache or CacheManager or exceptions while doing IO can corrupt the data. If that happens, you will have to clear the data folder before you can restart your cache.
For more details, see the Ehcache 2.7 persistence documentation.
Have you tried this?
<cache eternal="true"
maxElementsInMemory="0"
name="<cache name>"
overflowToDisk="true"/>
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).
I'm trying to configure ehcache with openjpa. I get the following error:
org.apache.openjpa.lib.util.ParseException:
Instantiation of plugin "DataCacheManager" with value "ehcache" caused an error
"java.lang.IllegalArgumentException: java.lang.ClassNotFoundException: ehcache".
The alias or class name may have been misspelled, or the class may not have be available in the class path.
Valid aliases for this plugin are: [default]
here's my excerpt from persistence.xml:
<property name="openjpa.QueryCache" value="ehcache" />
<property name="openjpa.DataCacheManager" value="ehcache" />
here's my ehcache.xml:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect" dynamicConfig="true">
<!-- -->
<cache name="openjpa" maxElementsInMemory="10000"
maxElementsOnDisk="1000" eternal="false" overflowToDisk="true"
diskSpoolBufferSizeMB="20" timeToIdleSeconds="300"
timeToLiveSeconds="600" memoryStoreEvictionPolicy="LFU"
transactionalMode="on" />
</ehcache>
And here's my pom.xml plugin dependency:
net.sf.ehcache
ehcache-openjpa
0.2.0
Is there any other way to configure openjpa+ehcache?
Yes it should work. Make sure that the ehcache-openjpa jar is on your classpath. I know this is slightly more complicated if you are running in a container environment(ie: WAS).
[update]
I know I had this working at one point and I had to do something funny with WAS shared libraries to get this to work, but I can't find any of my notes. I vaugely recollect that the problem had to do with OpenJPA not detecting Ehcache at start up, in turn we didn't register the 'ehcache' aliases.
Try configuring OpenJPA with the following properties :
<property name="openjpa.QueryCache" value="net.sf.ehcache.openjpa.datacache.EhCacheQueryCache"/>
<property name="openjpa.DataCacheManager" value="net.sf.ehcache.openjpa.datacache.EhCacheDataCacheManager"/>
<property name="openjpa.DataCache" value="net.sf.ehcache.openjpa.datacache.EhCacheDataCache"/>
<property name="openjpa.RemoteCommitProvider" value="net.sf.ehcache.openjpa.datacache.NoOpRemoteCommitProvider"/>
[/update]
I think my Hibernate (3.5.3) Second Level Cache is well configured with EhCache (2.2).
At least, I observe following log entries:
20:15:28 DEBUG [net.sf.ehcache.Cache#searchInStoreWithStats] persistence.unit:unitName=#pu-pay.c.u.p.model.ActionCache: persistence.unit:unitName=#pu-pay.c.u.p.model.Action store hit for c.u.p.model.Action#TRT
20:15:28 DEBUG [net.sf.ehcache.Cache#searchInStoreWithStats] persistence.unit:unitName=#pu-pay.c.u.p.model.ActionCache: persistence.unit:unitName=#pu-pay.c.u.p.model.Action store hit for c.u.p.model.Action#PID
(... do these "store hits" really indicate that the cache is working?)
What puzzles me now is:
When I inspect the statistics as follows:
cacheManager.getCache("persistence.unit:unitName=#pu-pay.c.u.p.model.Action").getStatistics().toString()
... all I see is:
name = persistence.unit:unitName=#pu-pay.c.u.p.model.Action cacheHits = 0 onDiskHits = 0 inMemoryHits = 0 misses = 0 size = 0 averageGetTime = 0.0 evictionCount = 0
... no hits, no misses,... nothing...
In ehcache.xml, I have:
<defaultCache
...
statistics="true"
...
/>
<cache
name="persistence.unit:unitName=#pu-pay.c.u.p.model.Action"
maxElementsInMemory="100"
eternal="true"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="false"
statistics="true"
/>
Does this ring a bell to any body? Do I have to enable statistics in another location as well? ...
Update:
persistence.xml specifies:
<property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.EhCacheRegionFactory"/>
<property name="hibernate.cache.use_query_cache" value="false"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.generate_statistics" value="true"/>
Weird indeed, these debug statement do mean you are having hits to the ersistence.unit:unitName=#pu-pay.c.u.p.model.Action Cacheā¦ I wonder whether your CacheManager is the right one, could it be the Hibernate Provider is using another instance ?
How does your hibernate config look like ?