On Jan 23, 2009, at 6:12 PM, Brad Douglas wrote:

Hi there,

I'm trying to migrate my testing framework from JBoss Embedded to OpenEJB
but have run into a bit of a dead end.  A lot of my tests are just
exercising entities etc to ensure that they behavour properly (including
constraints etc).  We have an abstract EBJTest class which contains a
reference to the EntityManager, extended used by the test classes for each
entity.  The EJBTest class initialises the container then gets an
EntityManager instance via JNDI lookup:
   entityManager = (EntityManager)
ctx.lookup("java:/EntityManagers/LibertyEM");
   transactionManager = (TransactionManager)
ctx.lookup("java:/TransactionManager");

I've seen the page at
http://openejb.apache.org/3.0/injection-of-entitymanager- example.html that outlines how to objtain an EntityManager via injection. I've been able to cut over the code for the container initialisation OK, but I can't find any
examples where an EntityManager instance is obtained outside of a EJB.

Is the a way to get an EntityManager reference in a scenerio like this or
would I need to rework all the tests?

Hi Brad,

The use of an inner-class EJB is great for getting anything you need that an EJB can have. Something like this:

import junit.framework.TestCase;

import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import static javax.ejb.TransactionManagementType.BEAN;
import javax.annotation.Resource;
import javax.transaction.UserTransaction;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.EntityManager;
import javax.naming.Context;
import javax.naming.InitialContext;
import java.util.Properties;

public class EJBTest extends TestCase {

    private EntityManager entityManager;
    private UserTransaction userTransaction;

    @Override
    protected void setUp() throws Exception {
        Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
        // set any other properties

        InitialContext initialContext = new InitialContext(p);
EJBTestLocal ejbTestLocal = (EJBTestLocal) initialContext.lookup("EJBTestBeanLocal");

        entityManager = ejbTestLocal.getEntityManager();
        userTransaction = ejbTestLocal.getUserTransaction();
    }


    /**
     * The src/test/resource/META-INF/ejb-jar.xml will cause this
     * EJB to be automatically discovered and deployed when
     * OpenEJB boots up.
     */
    @Stateless
    @TransactionManagement(BEAN)
    public static class EJBTestBean implements EJBTestLocal {

        @Resource
        private UserTransaction userTransaction;

        @PersistenceContext(type = PersistenceContextType.EXTENDED)
        private EntityManager entityManager;

        public UserTransaction getUserTransaction() {
            return userTransaction;
        }

        public EntityManager getEntityManager() {
            return entityManager;
        }
    }

    public static interface EJBTestLocal {
        EntityManager getEntityManager();
        UserTransaction getUserTransaction();
    }

}

Note that to get OpenEJB to pickup your test bean you need to have a META-INF/ejb-jar.xml in your test classes directory.

The above uses the UserTransaction which is really just a thin wrapper on the TransactionManager itself. If you have a ton of code that uses the TransactionManager directly though, you can look it up from the TestCase like so:

        InitialContext context = new InitialContext();
        context.lookup("java:comp/TransactionManager");

There is a temporary limitation that the above lookup will only work if you do it outside an EJB (i.e. in your TestCase) and do not use the InitialContext(Properties) constructor. We plan to do some significant JNDI work in the future so hopefully it won't be that way for long.


Hope this helps!


-David



Reply via email to