Hello, I'm doing CRUD tests on a collection of integrated entities in a shared persistence unit, and am encountering some errors because of crufty tables from previous tests. I'm looking for a means of guaranteeing that the tables for each of my entities is devoid of entries after each test runs. The appropriate place to do this would be in the tearDown() method of the unit test class.
My environment is OpenEJB (3.0.0 core, latest snapshot), OpenJPA and an in-memory HSQLDB. OS X on Java 5. At the moment, I've implemented a stateless session bean to manage persistence for me. It's using an injected entity manager to perform a series of DELETE statements. Here's how the EM is set up: @PersistenceContext(unitName = "party-test-unit", type = PersistenceContextType.TRANSACTION) private EntityManager entityManager; I want to stress that I was previously removing entries from the database by getting a list of components of a given class, then iteratively deleting them. This worked just fine, but was very inefficient and slowed down the builds more than was acceptable. My clear() method defines a String[] of table names, then recursively creates a Query("DELETE FROM " + table) for each of the bean class names in the package I'm testing. Here is the code: public void clear() { Set<Query> queries = new HashSet<Query>(); String[] types = { "Address", "AssociatedAddress", "EmailAddress", "GeographicAddress", "ISOCountryCode", "Locale", "TelecomAddress", "WebPageAddress", "AssignedResponsibility", "Capability", "PartyRelationship", "PartyRelationshipType", "PartyRole", "PartyRoleType", "Responsibility", "Organization", "OrganizationName", "Party", "PartySignature", "Person", "PersonName", "Preference", "PreferenceOption", "PreferenceType", "Property", "RegisteredIdentifier"}; for(String table : types) { queries.add(entityManager.createQuery("DELETE FROM " + table)); } for(Query query : queries) query.executeUpdate(); } This method *usually* works. However, sometimes I get *very* strange nonapplication exceptions that are causing what appear to be intermittent test failures. By intermittent I mean a given unit test method might pass during one "mvn clean build" process, then fail immediately afterward during a second "mvn clean build" process, without any alterations to the source or testing code. This happens on some tests, sometimes, and not on others, other times, and I can discern no clear pattern. One example of the error output is listed at the bottom of this message. So, what I'm really looking for is a performant way to guarantee that my tables are empty between unit tests, so that I'm essentially starting from a completely clean environment. I welcome any suggestions, and will even entertain non-specification compliant mechanisms provided by OpenEJB or OpenJPA to accomplish this. Dain mentioned that I might completely drop and restart OpenEJB between tests. He also mentioned that OpenJPA might have a way to wipe the database tables clean for a given persistence unit. I'm interested in any ideas or feedback about this. Regards, -- Alexander R. Saint Croix As promised, here is the error: ------------------------------------------------------------------------------- Test set: org.eremite.corm.party.PersistenceTest ------------------------------------------------------------------------------- Tests run: 8, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 5.749 sec <<< FAILURE! testPartySignatureAnnotations(org.eremite.corm.party.PersistenceTest) Time elapsed: 0.466 sec <<< ERROR! javax.ejb.EJBException: The bean encountered a non-application exception.; nested exception is: <openjpa-1.0.1-r420667:592145 fatal general error> org.apache.openjpa.persistence.PersistenceException: no-saved-fields at org.apache.openejb.core.ivm.BaseEjbProxyHandler.convertException( BaseEjbProxyHandler.java:366) at org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke( BaseEjbProxyHandler.java:323) at org.apache.openejb.util.proxy.Jdk13InvocationHandler.invoke( Jdk13InvocationHandler.java:49) at $Proxy19.clear(Unknown Source) at org.eremite.corm.party.PersistenceTest.testPartySignatureAnnotations( PersistenceTest.java:189) 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:585) at junit.framework.TestCase.runTest(TestCase.java:164) at junit.framework.TestCase.runBare(TestCase.java:130) at junit.framework.TestResult$1.protect(TestResult.java:110) at junit.framework.TestResult.runProtected(TestResult.java:128) at junit.framework.TestResult.run(TestResult.java:113) at junit.framework.TestCase.run(TestCase.java:120) at junit.framework.TestSuite.runTest(TestSuite.java:228) at junit.framework.TestSuite.run(TestSuite.java:223) at org.junit.internal.runners.OldTestClassRunner.run( OldTestClassRunner.java:35) at org.apache.maven.surefire.junit4.JUnit4TestSet.execute( JUnit4TestSet.java:62) at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet( AbstractDirectoryTestSuite.java:138) at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute( AbstractDirectoryTestSuite.java:125) at org.apache.maven.surefire.Surefire.run(Surefire.java:132) 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:585) at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess( SurefireBooter.java:290) at org.apache.maven.surefire.booter.SurefireBooter.main( SurefireBooter.java:818) Caused by: <openjpa-1.0.1-r420667:592145 fatal general error> org.apache.openjpa.persistence.PersistenceException: no-saved-fields at org.apache.openjpa.kernel.StateManagerImpl.dirtyCheck( StateManagerImpl.java:799) at org.apache.openjpa.kernel.BrokerImpl$ManagedCache.dirtyCheck( BrokerImpl.java:4620) at org.apache.openjpa.kernel.BrokerImpl$ManagedCache.access$000( BrokerImpl.java:4360) at org.apache.openjpa.kernel.BrokerImpl.hasTransactionalObjects( BrokerImpl.java:3739) at org.apache.openjpa.kernel.BrokerImpl.setDirty(BrokerImpl.java:3856) at org.apache.openjpa.kernel.StateManagerImpl.setPCState( StateManagerImpl.java:207) at org.apache.openjpa.kernel.StateManagerImpl.dirty( StateManagerImpl.java:1532) at org.apache.openjpa.kernel.StateManagerImpl.dirty( StateManagerImpl.java:1471) at org.apache.openjpa.kernel.StateManagerImpl.dirtyCheck( StateManagerImpl.java:808) at org.apache.openjpa.kernel.BrokerImpl$ManagedCache.dirtyCheck( BrokerImpl.java:4620) at org.apache.openjpa.kernel.BrokerImpl$ManagedCache.access$000( BrokerImpl.java:4360) at org.apache.openjpa.kernel.BrokerImpl.hasTransactionalObjects( BrokerImpl.java:3739) at org.apache.openjpa.kernel.BrokerImpl.setDirty(BrokerImpl.java:3856) at org.apache.openjpa.kernel.StateManagerImpl.setPCState( StateManagerImpl.java:205) at org.apache.openjpa.kernel.StateManagerImpl.delete( StateManagerImpl.java:1070) at org.apache.openjpa.kernel.BrokerImpl.delete(BrokerImpl.java:2518) at org.apache.openjpa.kernel.SingleFieldManager.delete( SingleFieldManager.java:387) at org.apache.openjpa.kernel.SingleFieldManager.delete( SingleFieldManager.java:373) at org.apache.openjpa.kernel.SingleFieldManager.delete( SingleFieldManager.java:330) at org.apache.openjpa.kernel.SingleFieldManager.delete( SingleFieldManager.java:284) at org.apache.openjpa.kernel.StateManagerImpl.cascadeDelete( StateManagerImpl.java:2817) at org.apache.openjpa.kernel.BrokerImpl.delete(BrokerImpl.java:2517) at org.apache.openjpa.kernel.BrokerImpl.delete(BrokerImpl.java:2482) at org.apache.openjpa.kernel.QueryImpl.deleteInMemory(QueryImpl.java :1020) at org.apache.openjpa.kernel.ExpressionStoreQuery$DataStoreExecutor.executeDelete (ExpressionStoreQuery.java:684) at org.apache.openjpa.kernel.QueryImpl.delete(QueryImpl.java:1008) at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:801) at org.apache.openjpa.kernel.QueryImpl.deleteAll(QueryImpl.java:866) at org.apache.openjpa.kernel.QueryImpl.deleteAll(QueryImpl.java:862) at org.apache.openjpa.kernel.DelegatingQuery.deleteAll( DelegatingQuery.java:541) at org.apache.openjpa.persistence.QueryImpl.executeUpdate(QueryImpl.java :314) at org.eremite.corm.party.BeanManagerImpl.clear(BeanManagerImpl.java:66) 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:585) at org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke (ReflectionInvocationContext.java:146) at org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed( ReflectionInvocationContext.java:129) at org.apache.openejb.core.interceptor.InterceptorStack.invoke( InterceptorStack.java:67) at org.apache.openejb.core.stateless.StatelessContainer._invoke( StatelessContainer.java:210) at org.apache.openejb.core.stateless.StatelessContainer._invoke( StatelessContainer.java:188) at org.apache.openejb.core.stateless.StatelessContainer.invoke( StatelessContainer.java:165) at org.apache.openejb.core.ivm.EjbObjectProxyHandler.businessMethod( EjbObjectProxyHandler.java:217) at org.apache.openejb.core.ivm.EjbObjectProxyHandler._invoke( EjbObjectProxyHandler.java:77) at org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke( BaseEjbProxyHandler.java:321) ... 26 more