I have been using the hibernate3-maven-plugin for some time with a good deal of success in unit testing my data access layers through dbunit. I always separate my data access into a separate module, called data-services, for many reasons. Mostly so I can separate my testing to just database integration testing, and not unit testing in the test phase of maven. First, I create the hibernate3-maven-plugin declaration:
org.codehaus.mojo hibernate3-maven-plugin 2.2 hbm2hbmxml target/classes jpaconfiguration ApplicationEntityManager true ${maven.test.skip} src/test/resources/database.properties hbm2ddl process-test-resources hbm2ddl com.h2database h2 ${h2.version}
Notice the hbm2ddl execution phase is set to process-test-resources which is when the ddl is created. My database.properties to seed a file based H2 Database:
hibernate.connection.username=sa hibernate.connection.password= hibernate.dialect=org.hibernate.dialect.H2Dialect hibernate.connection.url=jdbc:h2:file:target/h2/testdb;REFERENTIAL_INTEGRITY=FALSE hibernate.connection.driver_class=org.h2.Driver
I also wanted all my tests to run in the integration-test phase, not the test phase
org.apache.maven.plugins maven-surefire-plugin ... surefire-unittest test **/*Test.java none surefire-it integration-test test none **/*Test.java
When I execute my normal “mvn clean verify -e”, I get the following trace:
[myproject] DEBUG [main] Ejb3Configuration.configure(312) | Processing PersistenceUnitInfo [ name: ApplicationEntityManager persistence provider classname: null classloader: sun.misc.Launcher$AppClassLoader@11b86e7 Temporary classloader: org.springframework.instrument.classloading.SimpleThrowawayClassLoader@11db6bb excludeUnlistedClasses: false JTA datasource: null Non JTA datasource: org.apache.commons.dbcp.BasicDataSource@1c7e2da Transaction type: RESOURCE_LOCAL PU root URL: file:/C:/opt/projects/grd/trunk/data-services/target/classes/
I plan on creating another post to detail my JUnit and TestNG DBUnit testing. For this post, I really just want to focus on the error in the hibernate3-maven-plugin. I have 21 tests run successfully:
Results : Tests run: 21, Failures: 0, Errors: 0, Skipped: 0
What I then wanted to do was integrate Cobertura Code Coverage into this module. I first added just a generic plugin delcaration:
org.codehaus.mojo cobertura-maven-plugin com.baselogic.ignore.* com/baselogic/**/*Test.class 85 85 true clean <!--<goal>check</goal>--> net.sourceforge.cobertura cobertura 1.9rc1
Notice I commented out the check as I did not want to fail the build, I wanted to allow lower numbers so I could generate the site documentation with these numbers. When I run “mvn site -e”, I get this error trying creating the ApplicationEntityManager stating a class or package was not found:
[INFO] [hibernate3:hbm2ddl {execution: hbm2ddl}] ... [myproject] DEBUG [main] Ejb3Configuration.configure(209) | Look up for persistence unit: ApplicationEntityManager [myproject] DEBUG [main] DTDEntityResolver.resolveEntity(64) | trying to resolve system-id [http://java.sun.com/xml/ns/p ersistence/persistence_1_0.xsd] [myproject] DEBUG [main] EJB3DTDEntityResolver.resolveEntity(49) | recognized EJB3 ORM namespace; attempting to resolve on classpath under org/hibernate/ejb [myproject] DEBUG [main] EJB3DTDEntityResolver.resolveEntity(58) | located [http://java.sun.com/xml/ns/persistence/persi stence_1_0.xsd] in classpath [myproject] DEBUG [main] Ejb3Configuration.getDetectedArtifacts(562) | Detect class: true; detect hbm: true [myproject] DEBUG [main] AbstractJarVisitor.unqualify(116) | Searching mapped entities in jar/par: file:/C:/opt/projects /grd/trunk/data-services/target/generated-classes/cobertura/ [myproject] DEBUG [main] AbstractJarVisitor.addElement(162) | Filtering: com.baselogic.dao.BaseDao [myproject] DEBUG [main] AbstractJarVisitor.addElement(162) | Filtering: com.baselogic.dao.jpa.BaseDaoJpaImpl$1 [myproject] DEBUG [main] AbstractJarVisitor.addElement(162) | Filtering: com.baselogic.dao.jpa.BaseDaoJpaImpl [myproject] DEBUG [main] AbstractJarVisitor.addElement(162) | Filtering: com.baselogic.domain.IdentifiedObject [myproject] DEBUG [main] AbstractJarVisitor.executeJavaElementFilter(213) | Java element filter matched for com.baselogi c.domain.IdentifiedObject [myproject] DEBUG [main] AbstractJarVisitor.addElement(162) | Filtering: com.baselogic.domain.User [myproject] DEBUG [main] AbstractJarVisitor.executeJavaElementFilter(213) | Java element filter matched for com.baselogi c.domain.User [myproject] DEBUG [main] AbstractJarVisitor.addElement(162) | Filtering: com.baselogic.domain.UserNotFoundException [myproject] DEBUG [main] AbstractJarVisitor.addElement(162) | Filtering: com.baselogic.service.impl.UserManagerImpl [myproject] DEBUG [main] AbstractJarVisitor.addElement(162) | Filtering: com.baselogic.service.UserManager [myproject] DEBUG [main] AbstractJarVisitor.addElement(162) | Filtering: com.fedex.ground.configuration.DataSourceFactor y [myproject] DEBUG [main] Ejb3Configuration.getDetectedArtifacts(562) | Detect class: true; detect hbm: true [myproject] DEBUG [main] Ejb3Configuration.configure(158) | Creating Factory: ApplicationEntityManager [INFO] ------------------------------------------------------------------------ [ERROR] FATAL ERROR [INFO] ------------------------------------------------------------------------ [INFO] [PersistenceUnit: ApplicationEntityManager] class or package not found com.baselogic.domain.IdentifiedObject [INFO] ------------------------------------------------------------------------ [INFO] Trace javax.persistence.PersistenceException: [PersistenceUnit: ApplicationEntityManager] class or package not found at org.hibernate.ejb.Ejb3Configuration.addNamedAnnotatedClasses(Ejb3Configuration.java:1093) at org.hibernate.ejb.Ejb3Configuration.addClassesToSessionFactory(Ejb3Configuration.java:871) at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:758) at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:191) at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:253) at org.codehaus.mojo.hibernate3.configuration.JPAComponentConfiguration.createConfiguration(JPAComponentConfigur ation.java:28) at org.codehaus.mojo.hibernate3.configuration.AbstractComponentConfiguration.getConfiguration(AbstractComponentC onfiguration.java:51) at org.codehaus.mojo.hibernate3.exporter.Hbm2DDLExporterMojo.doExecute(Hbm2DDLExporterMojo.java:87) at org.codehaus.mojo.hibernate3.HibernateExporterMojo.execute(HibernateExporterMojo.java:152) at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:453) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:559) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:50 0) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.forkProjectLifecycle(DefaultLifecycleExecutor.java:925) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.forkLifecycle(DefaultLifecycleExecutor.java:768) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:550) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:50 0) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:479) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.jav a:331) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:292) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:142) at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:336) at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:129) at org.apache.maven.cli.MavenCli.main(MavenCli.java:301) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315) at org.codehaus.classworlds.Launcher.launch(Launcher.java:255) at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430) at org.codehaus.classworlds.Launcher.main(Launcher.java:375) Caused by: java.lang.ClassNotFoundException: com.baselogic.domain.IdentifiedObject at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at org.codehaus.classworlds.RealmClassLoader.loadClassDirect(RealmClassLoader.java:195) at org.codehaus.classworlds.DefaultClassRealm.loadClass(DefaultClassRealm.java:255) at org.codehaus.classworlds.DefaultClassRealm.loadClass(DefaultClassRealm.java:274) at org.codehaus.classworlds.RealmClassLoader.loadClass(RealmClassLoader.java:214) at java.lang.ClassLoader.loadClass(ClassLoader.java:252) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:247) at org.hibernate.util.ReflectHelper.classForName(ReflectHelper.java:135) at org.hibernate.ejb.Ejb3Configuration.classForName(Ejb3Configuration.java:1009) at org.hibernate.ejb.Ejb3Configuration.addNamedAnnotatedClasses(Ejb3Configuration.java:1081) ... 30 more
I first started looking for the missing class file. I found 2. One in ~target/classes/**/IdentifiedObject.class and another one in ~target/cobertura/**/IdentifiedObject.class. The class was not missing, but it appeared that the hibernate3 plugin was not finding the correct classpath when running these tests instrumented with Cobertura. Remember, the tests run without Cobertura. I wanted to test to make sure Cobertura was running all, so in the above plugin deplaration, Iuncommented the check section and re-ran “mvn clean verify -e” to find that Cobertura was indeed running successfully, and failing the build:
[INFO] [cobertura:check {execution: default}] Cobertura: Loaded information on 11 classes. ... Project failed check. Total branch coverage rate of 55.8% is below 85.0% Project failed check. Total line coverage rate of 74.6% is below 85.0% ... [INFO] Coverage check failed. See messages above. [INFO] ------------------------------------------------------------------------
This tells me that Cobertura is instrumenting my DBUnit code, and my tests are running against my H2 file database, but there is not enough code coverage for my checked limits. This at least verifies that Cobertura works. After quite a bit of trial and error, I tried to change the phase in which the hibernate3 plugin was getting executed. I changed from process-test-resources and moved the execute further down the lifecycle to package. Now, when I can “mvn site -e”, I generate my site documentation successfully, as well as get my Cobertura report So now, I wanted to see the effect this change would have on my normal build life cycle, so I re-ran “mvn clean verify -e”. I was faced with more frustration, as now, my plugin was not running in the correct life cycle and all my dbunit test inserts where failing:
[myproject] DEBUG [main] AbstractHibernateTest.prepareDataSet(101) | Invoked prepareDataSet() prepareSettings called org.dbunit.dataset.NoSuchTableException: app_user at org.dbunit.database.DatabaseDataSet.getTableMetaData(DatabaseDataSet.java:279)
I have seen this error before and knew that my database was not created by the hibernate3 plugin. I decided to add a property to switch which phase the plugin would get executed. I added a default property process-test-resources to my pom’s … section. I then changed the hibernate3-maven-plugin phase from package to ${hibernate3.execute.phase} Now I needed to create a new profile jsut to switch this phased execution for my site:
lazy-hibernate3 package
Now I could easily use “mvn site -Plazy-hibernate3 -e” to lazily execute my hibernate3-maven-plugin
Recent Comments