You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomee.apache.org by Kevin Mudrick <km...@healthmarketscience.com> on 2008/04/08 21:59:28 UTC

variation on injection-of-entitymanager test

Hi,

If I change the injection-of-entitymanager test code to be 
container-managed and require new transactions for ejb calls, the unit 
tests fail:

ex:

@Stateful(name = "Movies")
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class MoviesImpl implements Movies {
   @PersistenceContext(unitName = "movie-unit", type = 
PersistenceContextType.TRANSACTION)
  private EntityManager entityManager;

  ...


I'm pretty sure this is a valid case, but the operation's don't seem to 
be commiting on each call into the bean from the test code:

Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 3.988 
sec <<< FAILURE!
test(org.superbiz.injection.jpa.MoviesTest)  Time elapsed: 3.939 sec  
<<< FAILURE!
junit.framework.AssertionFailedError: Movies.getMovies() expected:<0> 
but was:<3>
        at junit.framework.Assert.fail(Assert.java:47)
        at junit.framework.Assert.failNotEquals(Assert.java:277)
        at junit.framework.Assert.assertEquals(Assert.java:64)
        at junit.framework.Assert.assertEquals(Assert.java:195)
        at org.superbiz.injection.jpa.MoviesTest.test(MoviesTest.java:61)


Why is this so?  Does some other configuration need to change to support 
this?

Thanks,
Kevin


Re: variation on injection-of-entitymanager test

Posted by David Blevins <da...@visi.com>.
On Apr 8, 2008, at 12:59 PM, Kevin Mudrick wrote:

> Hi,
>
> If I change the injection-of-entitymanager test code to be container- 
> managed and require new transactions for ejb calls, the unit tests  
> fail:
>
> ex:
>
> @Stateful(name = "Movies")
> @TransactionManagement(TransactionManagementType.CONTAINER)
> @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
> public class MoviesImpl implements Movies {
>  @PersistenceContext(unitName = "movie-unit", type =  
> PersistenceContextType.TRANSACTION)
> private EntityManager entityManager;
>
> ...
>
>
> I'm pretty sure this is a valid case, but the operation's don't seem  
> to be commiting on each call into the bean from the test code:
>
> Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed:  
> 3.988 sec <<< FAILURE!
> test(org.superbiz.injection.jpa.MoviesTest)  Time elapsed: 3.939  
> sec  <<< FAILURE!
> junit.framework.AssertionFailedError: Movies.getMovies()  
> expected:<0> but was:<3>
>       at junit.framework.Assert.fail(Assert.java:47)
>       at junit.framework.Assert.failNotEquals(Assert.java:277)
>       at junit.framework.Assert.assertEquals(Assert.java:64)
>       at junit.framework.Assert.assertEquals(Assert.java:195)
>       at org.superbiz.injection.jpa.MoviesTest.test(MoviesTest.java: 
> 61)
>
>
> Why is this so?  Does some other configuration need to change to  
> support this?

Hi Kevin.

The basics of what's happening is that when the example was switched  
from PersistenceContextType.EXTENDED to  
PersistenceContextType.TRANSACTION the persistence contract changed in  
a subtle way.

With EXTENDED, Entities stay attached outside the scope of a  
transaction and you can then use them again in a subsequent  
transaction without having to re-fetch them from the EntityManager via  
merge or something similar.  The test code, which isn't running in a  
transaction, is able to pull/pass Entities from/to the Stateful EJB,  
which runs in a transaction, only because of the EXTENDED persistence  
context.

With TRANSACTION as the PersistenceContext for the EntityManager, the  
Entities returned from the Stateful EJB detach when the transaction  
completes.  By the time the test case gets the java.util.List of  
entities, they've all been detached and often times (depending on the  
persistence provider) not even filled with data.  When detached, the  
Entities leave the "sight" of the EntityManager and are considered  
plain, non-persistent, java objects.  In the case of lists it's common  
to find that the EntityManager gave a "lazy" list and won't actually  
read the data associated with the query unless you iterate over the  
list in the transaction.  Both OpenJPA and Hibernate do that, not sure  
of others.

This document shows some techniques for running your test case in a  
transaction so that you can successfully test an EntityManager using a  
TRANSACTION persistence scope.  http://openejb.apache.org/3.0/unit-testing-transactions.html

Note that you'll still run into the detach issue if the bean uses  
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW).  Better  
would be to stick with the default of REQUIRED or (my preference) go  
with MANDATORY so that it isn't possible for others to call your bean  
outside of a transaction and get confusing results.

We have an example with that exact setup that you might find useful.   
It's the directory "testing-transactions" in the openejb- 
examples-3.0.zip released yesterday and available on the download page.

Hope this helps!

-David