Hibernate & EhCache: net.sf.ehcache.Statistics not populated? - java

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 ?

Related

How to have permanent cache using ehcache in spring mvc

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"/>

Hibernate Second Level Cache and Hudson

I'm using SecondLevelCache with hibernate. This is my xml configuration file:
<persistence-unit name="EntityTestHibernate" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.format_sql" value="false"/>
<property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/DB_NAME"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/>
<property name="hibernate.connection.username" value="USERNAME"/>
<property name="hibernate.connection.password" value="PASSWORD"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.EhCacheProvider" />
My ehcache.xml:
<ehcache name="cacheTest" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<defaultCache eternal="true" maxElementsInMemory="100" overflowToDisk="false" />
<cache name="entityCache"
maxEntriesLocalHeap="50"
eternal="false"
timeToLiveSeconds="120"
/>
</ehcache>
and on my entity there is an annotation like this
#Cache(region="entityCache", usage=CacheConcurrencyStrategy.READ_WRITE )
When i run locally my UnitTest i have no problems. All tests passed, but if i run tests on my Hudson continuos integretion i have following error (problem is same if i set or not annotation on it #DirtiesContext):
> javax.persistence.PersistenceException: org.hibernate.cache.CacheException: java.lang.IllegalStateException:
> The cacheTest Cache is not alive (STATUS_SHUTDOWN) at
> org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1167)
> at
> org.hibernate.ejb.AbstractEntityManagerImpl.refresh(AbstractEntityManagerImpl.java:673)
> at
> org.hibernate.ejb.AbstractEntityManagerImpl.refresh(AbstractEntityManagerImpl.java:641)
> Caused by: org.hibernate.cache.CacheException:
> java.lang.IllegalStateException: The cacheTest Cache is not alive
> (STATUS_SHUTDOWN) at
> net.sf.ehcache.hibernate.regions.EhcacheTransactionalDataRegion.remove(EhcacheTransactionalDataRegion.java:164)
> at
> net.sf.ehcache.hibernate.strategy.AbstractEhcacheAccessStrategy.evict(AbstractEhcacheAccessStrategy.java:119)
> at
> net.sf.ehcache.hibernate.nonstop.NonstopAwareEntityRegionAccessStrategy.evict(NonstopAwareEntityRegionAccessStrategy.java:96)
> at
> org.hibernate.event.def.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:144)
> at
> org.hibernate.event.def.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:62)
> at org.hibernate.impl.SessionImpl.fireRefresh(SessionImpl.java:1118)
> at org.hibernate.impl.SessionImpl.refresh(SessionImpl.java:1098) at
> org.hibernate.ejb.AbstractEntityManagerImpl.refresh(AbstractEntityManagerImpl.java:666)
> Caused by: java.lang.IllegalStateException: The cacheTest Cache is
> not alive (STATUS_SHUTDOWN) at
> net.sf.ehcache.Cache$CacheStatus.checkAlive(Cache.java:3946) at
> net.sf.ehcache.Cache.checkStatus(Cache.java:2664) at
> net.sf.ehcache.Cache.removeInternal(Cache.java:2288) at
> net.sf.ehcache.Cache.remove(Cache.java:2207) at
> net.sf.ehcache.Cache.remove(Cache.java:2125) at
> net.sf.ehcache.hibernate.regions.EhcacheTransactionalDataRegion.remove(EhcacheTransactionalDataRegion.java:160)
How could i solve that problem?
Why that happens only on Hudson?
UPDATE
As suggested by #lanimall i have:
disabled all nodes on Hudson;
modified persistence.xml.
Replacing
< property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.EhCacheProvider" />
with
<property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory" />
but that doesn't solve my problem (but it's a good starting :-)...error is same).
My environment configuration is hibernate3 and ehcache-2.7.2
what version of hibernate are you using? and Ehcache?
I think what could be happening is that hudson is running on some application server (such as Glassfish, Tomcat 5, JBoss, Jetty 6, etc) and it might have either some ehcache or hibernate lib versions that are competing with the ones you're embedding in your app...hence the problem happening only when running tests in hudson. Make sure to look into that...
Also, per ehcache/hibernate documentation (http://ehcache.org/documentation/user-guide/hibernate#Configure-Ehcache-as-the-Second-Level-Cache-Provider), please try to use the "hibernate.cache.region.factory_class" setting as opposed to the "hibernate.cache.provider_class"...
And I also usually use the singleton factory (otherwise your JUNIT tests will not work...). Based on hibernate version, use
hibernate.cache.region.factory_class=net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory
or (for hibernate 4.x and above)
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
hope that helps...
I have found solution!
In my persistence.xml i had 2 persistence-unit configured as Singleton and in some tests were used both. In that way those share EhCacheSingleton.
Then happens that when EntityFactory associated to one of that was shutdown, consequently make a ehcache shutdown that was used by the other one (because there is one instance of Singleton shared between those 2 entity manager).
Many thanks to #lanimall to open my mind!
JUnit share Spring context for speed. I've avoid from this exception when remove explicitly Spring context closing in one of my test.

Incorrect ehcache statistics: hits+misses == 0

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).

Configuring OpenJPA 1.3.1 with EhCache: plugin/alias not found

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]

Hibernate 2nd level cache

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.

Categories