This falls under the category of interesting hacks. It also falls under the category of "the goggles...they do nothing!". But it's Friday.
So I'm unit testing, and wanted to use OpenEJB's ability to run an SLSB in a transaction really only for the fact that that SLSB could then use an injected, transactional EntityManager without hassle. That is, really the thing I want to test is my JPA machinery--the mappings, the validations, etc. The easiest way to make this happen is to test an insert and retrieval with an EntityManager, and the easiest way to get an entity manager is to have one injected into a stateless session bean so you don't have to manage all the transactions for yourself. But I'm in unit test mode--I don't really want to create an SLSB and a TestCase for every stupid JPA scenario I want to test. Ideally I would {handwave handwave} have a transactional entity manager injected into my test case for me somehow but {handwave handwave} run as part of the EJB container {more handwaving}. But my test case is not an EJB. It is at the moment only a @LocalClient. Well, so, I made my TestCase both a @Stateless and a @LocalClient. :-) It implements a simple interface that basically defines what methods I want to have exposed through the local business interface. Ideally even this step wouldn't be necessary--once you can have an interfaceless SLSB in EJB 3.1, you can throw this step out. I annotate my test methods with @Test (from JUnit). I inject my @EJB (the test case itself!) into...uh...itself. :-) I also inject an EntityManager. Unfortunately the EntityManager shows up both "in" the test-case-as-EJB and the test-case-as-LocalClient. I just take care not to use it in the test-case-as-LocalClient methods. There is probably a way in @Before to null it out in such a case; I'll do that next. Anyhow, the net effect is that I can use an injected EntityManager in my test case which is effectively wrapped in itself as a SLSB. That's the part that makes my eyes go funny. Anyhow, it makes in-memory JPA testing pretty painless. The whole thing looks like this (the abstract test case I'm inheriting from does the OpenEJB initialization, but not much else; the code below is condensed for brevity): import javax.ejb.*; import javax.persistence.*; import org.junit.Test; import junit.openejb.AbstractOpenEJBTestCase; import org.apache.openejb.api.LocalClient; import static org.junit.Assert.*; @Stateless @LocalClient public class TestCaseXY extends AbstractOpenEJBTestCase implements TestClient { @EJB private TestClient tc; // a reference to...um...myself @PersistenceContext private EntityManager em; // The JUnit test method. Don't use the EntityManager here; // I think its behavior would be undefined since your // persistence.xml should be designating a JTA data source, // but you're not in a JTA context here. @Test public final void testXYClient() { assertNotNull(this.tc); this.tc.testXY(); // "Forward" to the "real" test method. } // The "real" test method. Run in a transaction, with EJB security, etc. @Override public void testXY() { assertNotNull(this.em); assertNotNull(this.tc); assertNotSame(this.tc, this); // Actual test code goes here } } // Interestingly, this doesn't have to be public so you can put it in the same file. interface TestClient { public void testXY(); } I hope someone finds this useful; feel free to get in touch (ell jay nelson at gee mayul dot com) if you have questions. Best, Laird