You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomee.apache.org by David Blevins <da...@visi.com> on 2009/08/15 02:35:30 UTC

Re: Local testing: programmatic reinitialization of container-supplied EMF?

We have a feature which might help:

  https://blogs.apache.org/openejb/entry/user_blog_restarting_the_embedded

We don't always control all the third-party libraries which is why  
internally we use the Surefire Forking approach to ensure we have an  
absolutely clean environment to test against, but definitely let us  
know if you run into issues with the close() approach.  We'll  
definitely do what we can to fix them even if they are third-party  
related.

-David


On Aug 13, 2009, at 1:07 PM, Laird Nelson wrote:

> I have a scenario that I have to assume is fairly commonplace.
>
> Following the instructions on the OpenEJB site, I've got a local  
> OpenEJB
> server running for my unit tests.  I park the thing on top of an in- 
> memory
> H2 database.  All fine and good.
>
> What I'd like to do is this:
>
>   - Wipe the database entirely between tests
>   - Cause the embedded OpenJPA to redo any configured DDL generation  
> before
>   each test
>
> Note that I'm not looking for what DBUnit does, namely resetting the
> database for you.  I want the JPA provider to take care of the DDL
> generation for me.
>
> Is there any way to do this?  H2 helps, somewhat, in that you can  
> open up an
> in-memory only database that will disappear when the last connection  
> to it
> is closed.  If I could get my grubby paws on the container-supplied  
> entity
> manager factory at some sort of global level and tell it to  
> reinitialize
> itself, then I could put that code at the beginning of each JUnit  
> test.
> This should close all the connections in the OpenJPA connection  
> pool, I'd
> think, thus wiping the H2 database; and would also, by virtue of
> reinitializing the EntityManagerFactory, cause the DDL generation to  
> fire
> again.  The net result is that all my EJBs under test would be  
> initialized
> with a blank database in between tests.
>
> I hope I'm making sense.  Does anyone have a recipe for doing this?
>
> Thanks,
> Laird


Re: Local testing: programmatic reinitialization of container-supplied EMF?

Posted by Laird Nelson <lj...@gmail.com>.
On Fri, Aug 14, 2009 at 8:35 PM, David Blevins <da...@visi.com>wrote:

> We have a feature which might help:
>
>  https://blogs.apache.org/openejb/entry/user_blog_restarting_the_embedded
>
> We don't always control all the third-party libraries which is why
> internally we use the Surefire Forking approach to ensure we have an
> absolutely clean environment to test against, but definitely let us know if
> you run into issues with the close() approach.  We'll definitely do what we
> can to fix them even if they are third-party related.
>

Ah, this is great.  Thanks.

Best,
Laird

Re: Local testing: programmatic reinitialization of container-supplied EMF?

Posted by Laird Nelson <lj...@gmail.com>.
On Mon, Aug 17, 2009 at 1:59 PM, David Blevins <da...@visi.com>wrote:

> I had a look in the "destroy" code and we do unbind all configured
> resources from JNDI so they will be garbage collected, as well we call
> stop() on all ResourceAdapter impls.  The DataSource pool doesn't implement
> the ResourceAdapter interface so therefore isn't getting explicitly closed.
>  We use a variation of commons-dbcp, looking around to see if there's some
> way to close the pool -- don't see anything just yet.


OK, that might give me something to go on.


> One clever way to work around the issue with the existing code might be to
> specify a different in memory db name for each test.  Maybe something like:
>
>  properties.setProperty("test.JdbcUrl", testDatabaseConnectionURL +
> (count++));
>

Yeah, I thought of that too; haven't tried it.  I am suspicious, because my
persistence.xml JTA DataSource name would remain the same, and I just have
this funny feeling that something in OpenJPA-land will cache the DDL or
something for a persistence unit whose name and DataSource don't change.
Admittedly, this part is all supposition.  I'll give it a shot.


> Would be cool if Junit could inject the test name so you could use that as
> the in-memory db name.


Agreed, although these days JUnit 4.x doesn't have test names any more.
:-(  Unless I'm missing something in their immaculately documented {cough
cough} API.

Best,
Laird

Re: Local testing: programmatic reinitialization of container-supplied EMF?

Posted by David Blevins <da...@visi.com>.
On Aug 17, 2009, at 7:49 AM, Laird Nelson wrote:

> Hi, David; thanks for the tips.
>
> Two things of note:
>
>   1. Something I just discovered: SureFire forking doesn't actually  
> fork
>   per test, even if you tell it to.  That is, in JUnit 4, a test is  
> any method
>   annotated with @Test.  It appears to be the case that SureFire  
> will fork
>   once *per test class*, but that isn't the same thing.  If you only  
> have
>   one @Test method per class, then obviously this doesn't matter,  
> but in my
>   case I have several.  So SureFire forking on its own can't solve  
> my problem,
>   unless I move to a test architecture where I have one test method  
> per
>   class.  For various reasons I can't do that.

That would be a real pain as well.

>   2. The undocumented property called out in the article you  
> referenced
>   works great--but I don't think it causes the connection pool to  
> close.  That
>   is, the context does in fact close, and the container system is  
> destroyed,
>   and classpath.ear is undeployed.  But when the context is  
> reinitialized, the
>   DDL generation doesn't run again (and the H2 database is not  
> zapped).  I'm
>   using a way of opening an H2 database so that when the last  
> connection to
>   the database is closed, the database is destroyed.  The fact that  
> the
>   database is still present for the second test run tells me that the
>   connection pool is not also being destroyed as part of the context  
> shutdown.

I had a look in the "destroy" code and we do unbind all configured  
resources from JNDI so they will be garbage collected, as well we call  
stop() on all ResourceAdapter impls.  The DataSource pool doesn't  
implement the ResourceAdapter interface so therefore isn't getting  
explicitly closed.  We use a variation of commons-dbcp, looking around  
to see if there's some way to close the pool -- don't see anything  
just yet.

One clever way to work around the issue with the existing code might  
be to specify a different in memory db name for each test.  Maybe  
something like:

   properties.setProperty("test.JdbcUrl", testDatabaseConnectionURL +  
(count++));

Would be cool if Junit could inject the test name so you could use  
that as the in-memory db name.

>
> In case it helps, here's how I'm building my context:
>
>    final Properties properties = new Properties();
>    properties.putAll(System.getProperties()); // allow for -D  
> properties to
> affect context construction

Just a note that this is default behavior for any props that OpenEJB  
understands.  Internally we first grab a copy of the system properties  
the overlay the initial context properties, then use the result.

Definitely let us know if there's a situation where that isn't working  
for you.

-David


Re: Local testing: programmatic reinitialization of container-supplied EMF?

Posted by Laird Nelson <lj...@gmail.com>.
Hi, David; thanks for the tips.

Two things of note:

   1. Something I just discovered: SureFire forking doesn't actually fork
   per test, even if you tell it to.  That is, in JUnit 4, a test is any method
   annotated with @Test.  It appears to be the case that SureFire will fork
   once *per test class*, but that isn't the same thing.  If you only have
   one @Test method per class, then obviously this doesn't matter, but in my
   case I have several.  So SureFire forking on its own can't solve my problem,
   unless I move to a test architecture where I have one test method per
   class.  For various reasons I can't do that.
   2. The undocumented property called out in the article you referenced
   works great--but I don't think it causes the connection pool to close.  That
   is, the context does in fact close, and the container system is destroyed,
   and classpath.ear is undeployed.  But when the context is reinitialized, the
   DDL generation doesn't run again (and the H2 database is not zapped).  I'm
   using a way of opening an H2 database so that when the last connection to
   the database is closed, the database is destroyed.  The fact that the
   database is still present for the second test run tells me that the
   connection pool is not also being destroyed as part of the context shutdown.

In case it helps, here's how I'm building my context:

    final Properties properties = new Properties();
    properties.putAll(System.getProperties()); // allow for -D properties to
affect context construction
    properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
LocalInitialContextFactory.class.getName());
    properties.setProperty("openejb.jndiname.format",
"{interfaceType.annotationName}/{deploymentId}/{interfaceClass}");
    // See
http://blog.jonasbandi.net/2009/06/restarting-embedded-openejb-container.html
    properties.setProperty("openejb.embedded.initialcontext.close",
"destroy");
    final String testDatabaseConnectionURL =
properties.getProperty("testDatabaseConnectionURL"); // passed in via -D
    if (testDatabaseConnectionURL != null) {
      properties.setProperty("test", "new://Resource?type=DataSource"); //
create a DataSource
      System.out.println("Using JdbcUrl: " + testDatabaseConnectionURL);
      properties.setProperty("test.JdbcUrl", testDatabaseConnectionURL);
      properties.setProperty("test.JdbcDriver",
properties.getProperty("testDatabaseDriverClass"));
      properties.setProperty("test.Username",
properties.getProperty("testDatabaseUser"));
      properties.setProperty("test.Password",
properties.getProperty("testDatabasePassword"));
    }
    System.out.println("Initializing context");
    this.context = new InitialContext(properties);

Now the DataSource I create in line 9 above I am presuming causes the
allocation of some connections to whatever database I've specified in my
testDatabaseConnectionURL (usually jdbc:h2:mem:test).

When I close the context, via this.context.close(), I see this in the
output:

INFO - Destroying container system
INFO - Undeploying app: classpath.ear

I don't see anything to indicate that the DataSource Resource I created in
line 9 is destroyed, and, as I said, once I reinitialize the context--using
the same code I've got above--I do NOT see the DDL regenerated (which
indicates to me there is still a connection to the H2 database somewhere).

Any ideas on how to work around this?

Thanks,
Laird

On Fri, Aug 14, 2009 at 8:35 PM, David Blevins <da...@visi.com>wrote:

> We have a feature which might help:
>
>  https://blogs.apache.org/openejb/entry/user_blog_restarting_the_embedded
>
> We don't always control all the third-party libraries which is why
> internally we use the Surefire Forking approach to ensure we have an
> absolutely clean environment to test against, but definitely let us know if
> you run into issues with the close() approach.  We'll definitely do what we
> can to fix them even if they are third-party related.
>
> -David
>
>
>
> On Aug 13, 2009, at 1:07 PM, Laird Nelson wrote:
>
>  I have a scenario that I have to assume is fairly commonplace.
>>
>> Following the instructions on the OpenEJB site, I've got a local OpenEJB
>> server running for my unit tests.  I park the thing on top of an in-memory
>> H2 database.  All fine and good.
>>
>> What I'd like to do is this:
>>
>>  - Wipe the database entirely between tests
>>  - Cause the embedded OpenJPA to redo any configured DDL generation before
>>  each test
>>
>> Note that I'm not looking for what DBUnit does, namely resetting the
>> database for you.  I want the JPA provider to take care of the DDL
>> generation for me.
>>
>> Is there any way to do this?  H2 helps, somewhat, in that you can open up
>> an
>> in-memory only database that will disappear when the last connection to it
>> is closed.  If I could get my grubby paws on the container-supplied entity
>> manager factory at some sort of global level and tell it to reinitialize
>> itself, then I could put that code at the beginning of each JUnit test.
>> This should close all the connections in the OpenJPA connection pool, I'd
>> think, thus wiping the H2 database; and would also, by virtue of
>> reinitializing the EntityManagerFactory, cause the DDL generation to fire
>> again.  The net result is that all my EJBs under test would be initialized
>> with a blank database in between tests.
>>
>> I hope I'm making sense.  Does anyone have a recipe for doing this?
>>
>> Thanks,
>> Laird
>>
>
>