Hibernate Second Level Cache and Hudson - java

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.

Related

Wildfly Data Persistence

I am currently working on a Java EE project and am working with the Wildfly server.
I have a Web project and EJB project which are deployed onto the Wildfly server.
I can save a user for example, but only for as long as the server is running.
There is no data persistence between server downtimes.
I have searched through the internet but couldn't find an answer.
My persistence.xml looks like this:
<persistence-unit name="primary">
<!-- If you are running in a production environment, add a managed
data source, this example data source is just for development and testing! -->
<!-- The datasource is deployed as WEB-INF/kitchensink-quickstart-ds.xml, you
can find it in the source at src/main/webapp/WEB-INF/kitchensink-quickstart-ds.xml -->
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
<properties>
<!-- Properties for Hibernate -->
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="false" />
<value="true"/>
</properties>
If I want to persist any information, do i need to reconfigure this file?
I hope you can help me :)
Your problem is this line
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
Everytime when the wildfly starts up, JPA creates a new database model with an empty database.
Adjust your code to
<property name="hibernate.hbm2ddl.auto" value="update" />
You are using "ExampleDS" which is set up as H2 in-memory database by default. It therefore does not persist data between restarts on purpose (useful for development/testing). Go to wildfly's standalone/configuration/standalone.xml configuration file and search for "ExampleDS" in the "datasources" section. It should show:
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
where "mem" means in-memory. You can change "mem:test" to any write path, e.g.
<connection-url>jdbc:h2:~/test;DB_CLOSE_DELAY=-1</connection-url>
to use a H2 file-based database stored as "test" in your home-folder (assuming *nix).
You can also define additional databases (Postgresql, Oracle, etc) in the datasources-section.

Application startup fail for weblogic restart and success for second time. (With differen openjpa metada)

it's difficult to describe case so below short case and result of my investigation:
Environment:
java 1.6
weblogic-10.3.6.0
openjpa - 1.1.0
spring - 3.2
Two persistence-unit in one persistence.xml (A and R)
Case:
Deploy war file to weblogic is successful
Stop app in admin console
Try start app - it's Failed
Try start again - it's success!
stacktrace
weblogic.application.ModuleException: :org.apache.openjpa.persistence.ArgumentException:Table "ACTION_COMMENT" given for "......ActionComment" does not exist.
at org.apache.openjpa.jdbc.meta.MappingInfo.createTable(MappingInfo.java:470)
at org.apache.openjpa.jdbc.meta.ClassMappingInfo.getTable(ClassMappingInfo.java:229)
at org.apache.openjpa.jdbc.meta.strats.FullClassStrategy.map(FullClassStrategy.java:71)
at org.apache.openjpa.jdbc.meta.ClassMapping.setStrategy(ClassMapping.java:381)
at org.apache.openjpa.jdbc.meta.RuntimeStrategyInstaller.installStrategy(RuntimeStrategyInstaller.java:55)
at org.apache.openjpa.jdbc.meta.MappingRepository.prepareMapping(MappingRepository.java:318)
at org.apache.openjpa.meta.MetaDataRepository.preMapping(MetaDataRepository.java:667)
at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:549)
at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:308)
at org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:248)
at org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:219)
at org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:187)
at org.apache.openjpa.enhance.ManagedClassSubclasser.prepareUnenhancedClasses(ManagedClassSubclasser.java:121)
at org.apache.openjpa.kernel.AbstractBrokerFactory.loadPersistentTypes(AbstractBrokerFactory.java:310)
at org.apache.openjpa.kernel.AbstractBrokerFactory.initializeBroker(AbstractBrokerFactory.java:228)
at org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:190)
at org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:142)
at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:192)
at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:145)
at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:56)
at org.springframework.orm.jpa.JpaTransactionManager.createEntityManagerForTransaction(JpaTransactionManager.java:445)
Investigation:
Failed case:
It's happen because ActionComment should be save in persistence-unit R, but jpa in MappingInfo try to find it in persistence-unit A.
org.apache.openjpa.jdbc.meta.MappingInfo line 466
Table table = group.findTable(fullName); group is org.apache.openjpa.jdbc.schema.LazySchemaFactory then in line 140
_conn = _conf.getDataSource2(null).getConnection(); return connection to persistence-unit A.
Successful case:
Stacktrace is different! Different behavior in org.apache.openjpa.kernel.AbstractBrokerFactory processing block from line 281 to 287
Collection c = new ArrayList(clss.size());
for (Iterator itr = clss.iterator(); itr.hasNext();) {
Class cls = (Class) itr.next();
c.add(cls.getName());
if (needsSub(cls))
toRedefine.add(cls);
}
In successful case result of this code block toRedefine collection is empty and code below (line 310 in AbstractBrokerFactory )
// get the ManagedClassSubclasser into the loop
ManagedClassSubclasser.prepareUnenhancedClasses(
_conf, toRedefine, envLoader) don't have any effect.
needsSub(cls)
private boolean needsSub(Class cls) {
return !cls.isInterface()
&& !PersistenceCapable.class.isAssignableFrom(cls);
}
For first restart (failed case) PersistenceCapable.class.isAssignableFrom(cls) return false and all method return true.
For second restart (success case) PersistenceCapable.class.isAssignableFrom(cls) return true and all method return false.
In cls ActionComment class, result of getClassLoader() call.
Failure case:
result = {weblogic.utils.classloaders.ChangeAwareClassLoader#26293}"weblogic.utils.classloaders.ChangeAwareClassLoader#fa3e780 finder: weblogic.utils.classloaders.CodeGenClassFinder#4ce80175 annotation: svwi#svwi-2.9.1-SHAPSHOT.war"
Success case
result = {weblogic.utils.classloaders.ChangeAwareClassLoader#29327}"weblogic.utils.classloaders.ChangeAwareClassLoader#3932d2a2 finder: weblogic.utils.classloaders.CodeGenClassFinder#44e8cb1e annotation: svwi#svwi-2.9.1-SHAPSHOT.war"
Could anybody help with it?
Update
persistence.xml
<?xml version="1.0"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="analysys" transaction-type="RESOURCE_LOCAL">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl
</provider>
<jta-data-source>AnalysisDS</jta-data-source>
<class>.....Rule</class>
...other classes..
<properties>
<property name="openjpa.ManagedRuntime" value="org.apache.openjpa.ee.JNDIManagedRuntime" />
<property name="openjpa.Log" value="SQL=TRACE"/>
<property name="openjpa.ConnectionFactoryProperties"
value="PrintParameters=true, PrettyPrint=true, PrettyPrintLineLength=72" />
<property name="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)"/>
<property name="openjpa.DetachState"
value="loaded(DetachedStateField=true, DetachedStateManager=true)" />
<property name="openjpa.IgnoreChanges" value="true" />
<property name="openjpa.jdbc.DBDictionary" value="oracle"/>
</properties>
</persistence-unit>
<persistence-unit name="reaction" transaction-type="RESOURCE_LOCAL">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl
</provider>
<jta-data-source>ReactionDS</jta-data-source>
<class>.....ActionComment</class>
...other classes..
<properties>
<property name="openjpa.ManagedRuntime" value="org.apache.openjpa.ee.JNDIManagedRuntime" />
<property name="openjpa.Log" value="SQL=TRACE"/>
<property name="openjpa.ConnectionFactoryProperties"
value="PrintParameters=true, PrettyPrint=true, PrettyPrintLineLength=72" />
<property name="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)"/>
<property name="openjpa.DetachState"
value="loaded(DetachedStateField=true, DetachedStateManager=true)" />
<property name="openjpa.IgnoreChanges" value="true" />
<property name="openjpa.jdbc.DBDictionary" value="oracle"/>
</properties>
</persistence-unit>

Unable to access datasource remotely through JBoss

Context
I have a JBoss where I have sucessfully deployed a datasource mydatasource-ds.xml.
It's JNDI name is java:mydatasourceDS. JBoss claims that the datasource is succesfully deployed. The JMX console agress too.
Problem
I want to use this datasource from a client java app launched on a separate JVM.
But I get an exception saying the java:mydatasourceDS cannot be found.
java.lang.ClassCastException: javax.naming.Reference cannot be cast to javax.sql.DataSource
Details
Here is the persistence.xml file :
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="mydatasource-db" transaction-type="JTA">
<jta-data-source>java:mydatasourceDS</jta-data-source>
<properties>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.default_schema" value="rec" />
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
</properties>
</persistence-unit>
Here is the jndi.properties file :
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
Here is the application classpath :
jndi.properties
log4j.properties
META-INF\persistence.xml
hibernate-jpa-2.0-api-1.0.0.Final.jar
jnp-client-5.0.3.GA.jar
jboss-common-core-2.2.14.GA.jar
jboss-logging-spi-2.1.0.GA.jar
hibernate-entitymanager-3.6.4.Final.jar
hibernate-core-3.6.4.Final.jar
antlr-2.7.6.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
hibernate-commons-annotations-3.2.0.Final.jar
jta-1.1.jar
javassist-3.12.0.GA.jar
slf4j-api-1.6.1.jar
slf4j-log4j12-1.6.1.jar
log4j-1.2.16.jar
xstream-1.4.1.jar
xmlpull-1.1.3.1.jar
xpp3_min-1.1.4c.jar
EDIT
I have found the source of the problem. The javax.sql.DataSource that was available to my client application was NOT the one received from JNDI. The one I receive from JNDI is the JBoss javax.sql.DataSource. Same name BUT slightly different classes hence the ClassCastException...
As of this writing, the JBoss javax.sql.DataSource can be found in this package : jboss-j2ee-4.2.3.GA.jar
If you get a
javax.naming.Reference
that means you are missing runtime dependencies that are required for it to resolve. You can inspect the classFactory member of the Reference object via
getFactoryClassName()
to figure out the first dependency you are missing.
In my case using JBoss6.1 it was:
org.jboss.resource.adapter.jdbc.remote.DataSourceFactory
Putting the jar this class is in on the classpath (common/lib/jbosscx-client.jar) got me past the first step and then it was a matter of tracking down all the ClassNotFoundException errors.
The full list for JBoss6.1 turned out to be:
- client/jnp-client.jar
- client/jboss-logging.jar
- common/lib/jbosscx-client.jar
- client/concurrent.jar
- client/jboss-client.jar
- client/jboss-common-core.jar
- client/jboss-integration.jar
- client/jboss-remoting.jar
- client/jboss-security-spi.jar
- client/jboss-serialization.jar
- client/jboss-transaction-api_1.1_spec.jar
This guide says that you have to set
<use-java-context>false</use-java-context>
in mydatasource-ds.xml. Not sure if you did.

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 & EhCache: net.sf.ehcache.Statistics not populated?

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 ?

Categories