Re: Nuking tables on tearDown() for CRUD tests

2008-01-09 Thread Alexander Saint Croix
David, Dain and I tested this last night, and here's the final conclusion we
came to.

The initial problem was that retrieving and iterating over a list of the
entities from the entity manager and deleting them one at a time is
incredibly slow (one of my test cases took 4 minutes and 23 seconds to run
through ten test methods for less than 100 entity instances) and the tests
slowed down to a crawl.  The persistence provider (in this case OpenJPA)
isn't built for this sort of usage, so we decided to try a second technique
involving executing native SQL queries directly against the database by way
of the EntityManager.

The queries we determined to run were a sequence of "DELETE FROM foo"
queries, where "foo" is replaced with the name of the actual table / class.
Thus, for Person objects, we'd execute a "DELETE FROM Person" query.

However, this is a potentially dangerous practice as well, for reasons which
are now clear.  I was deleting tables in an order that did not take into
consideration maintaining referential integrity of foreign keys.  Because
many of my objects are tightly integrated, it is important to delete the
tables in a particular order, such that reference objects are wiped clean
first.

I was able to isolate this behavior by experimentally altering the order of
table deletions.  Certain cases would always throw errors, others would
throw none.  The errors each had a characteristic error stack trace with
many repetitions of the following line:

WARN - Unexpected exception from afterCompletion; continuing
> 
> org.apache.openjpa.persistence.PersistenceException: no-saved-fields
> at org.apache.openjpa.kernel.StateManagerImpl.dirtyCheck(
> StateManagerImpl.java:799)
>

So, anywhere an entity table has a foreign key column you need to either
perform a cascading delete with the entityManager, nullify the reference
(assuming the foreign key columns are optional), or make certain to delete
the referencing bean first.

The recommended method to clear the foreign key columns is to run update
queries.  This is a good mechanism for breaking circular references on
teardown. An example looks like this:

"UPDATE Customer c set.myfk = null"

So, to sum things up, direct deletion against the database is much faster
than working through the EntityManager interface in some cases, but you need
to determine the precise order you are tearing items down, or design your
tests so that they are resilient to cruft in the database, if you intend on
running tests with an embedded OpenEJB container.

For the record, we also tried setting up the POM for the project to fork the
testing JVM, but this mechanism does not create a new JVM for each test
METHOD.  It only creates a new JVM for each test CASE.

I'm now running direct deletes, and being sensitive about foreign key
references, deletion order, and circular loops.  My final solution will
initially include a combination of direct deletes and EntityManager remove
calls via OpenJPA, and I will iteratively tune it until I've got a reliable
scraping method for my library.

One suggestion / idea for the future would be to provide a tool to analyze a
persistence unit and generate this sort of fast delete mechanism as an array
of query strings that could be serialized for any given persistence unit and
marshalled when needed for rapid clearing of the database during entity
tests.

A great big thanks to everyone on both teams who helped me isolate and
resolve this issue.
--
Alexander R. Saint Croix.



On Jan 8, 2008 8:21 PM, David Blevins <[EMAIL PROTECTED]> wrote:

> I swore I thought I mentioned using fork mode, but just in case.   If
> you use fork mode with the in-memory db, there's nothing to clean.
> Have you experimented with that route.
>
> We're still using jaxb to unmarshall the persistence.xml, but I've
> been thinking of cutting that out which might save you 1 second each
> test.  JAXB takes a while to initialize the first time it's used in a
> vm.
>
> -David


Re: Nuking tables on tearDown() for CRUD tests

2008-01-08 Thread David Blevins
I swore I thought I mentioned using fork mode, but just in case.   If  
you use fork mode with the in-memory db, there's nothing to clean.   
Have you experimented with that route.


We're still using jaxb to unmarshall the persistence.xml, but I've  
been thinking of cutting that out which might save you 1 second each  
test.  JAXB takes a while to initialize the first time it's used in a  
vm.


-David

On Jan 8, 2008, at 5:59 PM, Alexander Saint Croix wrote:

This was one suggestion by Adam Hardy on the [EMAIL PROTECTED] list.  I  
might
look into dbUnit, but wonder whether it is ideally suited for the  
container

injection mechanisms we're using.

Cheers,
--
Alex


-- Forwarded message --
From: Adam Hardy <[EMAIL PROTECTED]>
Date: Jan 8, 2008 5:52 PM
Subject: Re: Nuking tables on tearDown() for CRUD tests
To: [EMAIL PROTECTED]


Alexander Saint Croix on 08/01/08 23:08, wrote:
After working with devs on both the OpenEJB and the OpenJPA teams,  
I think

that for anything other than trivial persistence units and entity

relations,
it is probably necessary to manually find a list of all of the  
entities of

a
given type, iterate over that list, and use the  
entitymanager.remove()

method to clean out the entities in the datastore between unit tests.
Although this method is extremely slow and will be a big hit to
productivity, I cannot get a succession of "DELETE FROM table"  
queries to
reliably remove objects without crashing because of entity  
relations and

foreign keys, and have not yet had the former method crash on me.

The "DELETE FROM table" mechanism seems to wreak havoc on the  
cascading
rules and cause problems for itself when done in succession to  
multiple

tables--I don't know enough about the guts of the query execution

mechanism

to say why, and that's alright.  If we need to build an example

application
for either project to test this behavior at a later time, I'll be  
able to

provide a sufficiently complex persistence unit to really stress test
things.

In the meantime, I really am itching to get back to actual  
development, so
I'm going to revert and move forward using the other method for the  
time

being. Thanks to Dain, Panaki, Jacek, Adam, and Patrick.


I recommended DbUnit for handling test data before, and in terms of  
the

performance hit, it won't be much problem at all.

However it would require a list of all tables from which to delete,  
and it

must
be ordered to take account of referential integrity constraints.

DbUnit also allows you to store all data in XML files which can be  
loaded

fresh
for each test. Obviously this uses the same list of tables as above,  
just in
reverse. And you need to ditch and recreate the entity manager  
between each
test. It wasn't quick or easy to set up a system to handle the test  
data

like
this, but it's paid dividends.




Re: Nuking tables on tearDown() for CRUD tests

2008-01-08 Thread Alexander Saint Croix
After working with devs on both the OpenEJB and the OpenJPA teams, I think
that for anything other than trivial persistence units and entity relations,
it is probably necessary to manually find a list of all of the entities of a
given type, iterate over that list, and use the entitymanager.remove()
method to clean out the entities in the datastore between unit tests.
Although this method is extremely slow and will be a big hit to
productivity, I cannot get a succession of "DELETE FROM table" queries to
reliably remove objects without crashing because of entity relations and
foreign keys, and have not yet had the former method crash on me.

The "DELETE FROM table" mechanism seems to wreak havoc on the cascading
rules and cause problems for itself when done in succession to multiple
tables--I don't know enough about the guts of the query execution mechanism
to say why, and that's alright.  If we need to build an example application
for either project to test this behavior at a later time, I'll be able to
provide a sufficiently complex persistence unit to really stress test
things.

In the meantime, I really am itching to get back to actual development, so
I'm going to revert and move forward using the other method for the time
being. Thanks to Dain, Panaki, Jacek, Adam, and Patrick.

Cheers,
--
Alex


Re: Nuking tables on tearDown() for CRUD tests

2008-01-08 Thread Alexander Saint Croix
I'll try moving the string array into the client and running each delete in
a separate transaction.  I'll also see if altering the order of deletes
helps the process along.  Some of the relationships entail cascading
deletes, others do not, and not all are bidirectional, so depending on how
sensitive the data source or persistence provider are, I might have to go
carefully through the entities and figure out the proper order for them to
be deleted.  If some rules could be derived about that, we might look into
building tools to assist with this sort of process later on.

I'll let you know how it goes.  I have to admit, working on this is
addictive.

Cheers, and thanks!
--
Alex



On Jan 8, 2008 3:36 PM, Dain Sundstrom <[EMAIL PROTECTED]> wrote:

> Can you try running each delete query in a separate transaction?
> Something like this in your session bean:
>
> public void clear(String type) {
> Query query = entityManager.createQuery("DELETE FROM " + type)
> query.executeUpdate();
> }
>
>
> and something like this in the test case:
>
> protected void tearDown() {
> String[] types = {...};
> for(String type : types) {
> bean.clear(type);
> }
> }
>
> One final thing, if you have foreign key constrained relationships,
> you will need to make sure the cascade delete settings are correct.
> For example, if you have an order with many line items and foreign
> key constraints, you must delete the line items before the order can
> be deleted.  This is normally accomplished with a cascade delete
> setting on the relationship.
>
> -dain
>
> On Jan 6, 2008, at 2:42 PM, Alexander Saint Croix wrote:
>
> > 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 queries = new HashSet();
> > 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 

Re: Nuking tables on tearDown() for CRUD tests

2008-01-08 Thread Dain Sundstrom
Can you try running each delete query in a separate transaction?   
Something like this in your session bean:


public void clear(String type) {
Query query = entityManager.createQuery("DELETE FROM " + type)
query.executeUpdate();
}


and something like this in the test case:

protected void tearDown() {
String[] types = {...};
for(String type : types) {
bean.clear(type);
}
}

One final thing, if you have foreign key constrained relationships,  
you will need to make sure the cascade delete settings are correct.   
For example, if you have an order with many line items and foreign  
key constraints, you must delete the line items before the order can  
be deleted.  This is normally accomplished with a cascade delete  
setting on the relationship.


-dain

On Jan 6, 2008, at 2:42 PM, Alexander Saint Croix wrote:


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 queries = new HashSet();
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 encount

Re: Nuking tables on tearDown() for CRUD tests

2008-01-08 Thread Dain Sundstrom
This only works if he shuts down OpenEJB between each test method,  
which would be slow.


-dain

On Jan 6, 2008, at 3:44 PM, Jacek Laskowski wrote:


On Jan 6, 2008 11:42 PM, Alexander Saint Croix
<[EMAIL PROTECTED]> wrote:

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.


Here's one possible solution for you - the usage of in-memory db and
. Until
an em is in use the tables are there in db. Once it's closed, at
openejb shutdown, the tables will get dropped automatically. You may
also want to remove the target directory where the db sits in.

See http://www.jaceklaskowski.pl/wiki/ 
Zasady_zapisu_zmian_do_bazy_danych_w_JPA#Konfiguracja_JPA_- 
_persistence.xml

for some configuration settings. The article is about how entity
changes are persisted in db using different jpa providers and is
written in Polish, but the configuration files should be
well-understandable by non-Polish speakers too.

Jacek

--
Jacek Laskowski
http://www.JacekLaskowski.pl




Re: Nuking tables on tearDown() for CRUD tests

2008-01-06 Thread Alexander Saint Croix
I'll ask the OpenEJB guys if this is possible.

Cheers,
--
Alex



On Jan 6, 2008 7:46 PM, Pinaki Poddar <[EMAIL PROTECTED]> wrote:

>
> This error is related to dynamic runtime enhancement (my guess). If you
> can,
> switch to build-time enhancement, to verify this guess.
> --
> View this message in context:
> http://www.nabble.com/Nuking-tables-on-tearDown%28%29-for-CRUD-tests-tp14655065p14657182.html
> Sent from the OpenJPA Users mailing list archive at Nabble.com.
>
>


Re: Nuking tables on tearDown() for CRUD tests

2008-01-06 Thread Alexander Saint Croix
Jacek,

Thank you very much for the reply. I am using an in-memory db, and I tried
the property below with no success.  Because the db is in memory, there's
nothing to delete in the file system.

Cheers,
--
Alex



On Jan 6, 2008 5:44 PM, Jacek Laskowski <[EMAIL PROTECTED]> wrote:

> On Jan 6, 2008 11:42 PM, Alexander Saint Croix
> <[EMAIL PROTECTED]> wrote:
>
> > 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.
>
> Here's one possible solution for you - the usage of in-memory db and
>  value="buildSchema(SchemaAction='add,deleteTableContents')" />. Until
> an em is in use the tables are there in db. Once it's closed, at
> openejb shutdown, the tables will get dropped automatically. You may
> also want to remove the target directory where the db sits in.
>
> See
> http://www.jaceklaskowski.pl/wiki/Zasady_zapisu_zmian_do_bazy_danych_w_JPA#Konfiguracja_JPA_-_persistence.xml
> for some configuration settings. The article is about how entity
> changes are persisted in db using different jpa providers and is
> written in Polish, but the configuration files should be
> well-understandable by non-Polish speakers too.
>
> Jacek
>
> --
> Jacek Laskowski
> http://www.JacekLaskowski.pl
>


Re: Nuking tables on tearDown() for CRUD tests

2008-01-06 Thread Jacek Laskowski
On Jan 6, 2008 11:42 PM, Alexander Saint Croix
<[EMAIL PROTECTED]> wrote:

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

Here's one possible solution for you - the usage of in-memory db and
. Until
an em is in use the tables are there in db. Once it's closed, at
openejb shutdown, the tables will get dropped automatically. You may
also want to remove the target directory where the db sits in.

See 
http://www.jaceklaskowski.pl/wiki/Zasady_zapisu_zmian_do_bazy_danych_w_JPA#Konfiguracja_JPA_-_persistence.xml
for some configuration settings. The article is about how entity
changes are persisted in db using different jpa providers and is
written in Polish, but the configuration files should be
well-understandable by non-Polish speakers too.

Jacek

-- 
Jacek Laskowski
http://www.JacekLaskowski.pl