Embeddable EJB
One of the most common requests we hear from Enterprise JavaBeans developers is for improved unit testing support. The two biggest issues they raise are :
- Testing Local Session Beans is difficult since they're only accessible by way of the Remote EJB tier or the web tier.
- Regardless of bean type, it would be simpler to allow client code to run in the same JVM as the components under test.
Some Java EE implementations have solved these problems by adding a Java SE execution mode in which clients instantiate EJB components within the same JVM. While this is a great start, more work is needed to raise the level of portability and ensure broader support.
We've been discussing this topic extensively in the EJB 3.1 Expert Group. Here's an early look at a proposed solution we're calling Embeddable EJB :
The Embeddable EJB API allows client code to instantiate an EJB container that runs within its own JVM and classloader. The client uses a spec-defined bootstrapping API to start the container and identify the set of enterprise bean components for execution.
The embeddable EJB container provides a managed environment with support for the same basic services that exist within a Java EE runtime : injection, access to a component environment, container-managed transactions, container-managed persistence contexts, etc. In general, enterprise bean components are unaware of the kind of managed environment in which they are running. This allows maximum reusability of bean components across a wide range of testing and deployment scenarios without significant rework.
Let's look at an example. Here's a simple Stateless session bean that uses Java Persistence to implement some bank account operations :
1: @Stateless
2: public class AccountBean {
3:
4: @PersistenceContext EntityManager em;
5:
6: public void createAccount(int acctId) {
7:
8: Account account = new Account(acctId);
9:
10: em.persist(account);
11:
12: }
13: ...
14: }
Note that this is just a normal stateless session bean. It exposes business methods through a no-interface view. The bean implementation uses injection, container-managed transactions, and Java Persistence. There is no special API it must use to be capable of embeddable execution.
Here is some test code to execute the bean in an embeddable container :
1:
2: // Instantiate an embeddable EJB container and search the
3: // JVM class path for eligible EJB modules or directories
4: EJBContainer ejbC = EJBContainer.createEJBContainer();
5:
6: // Get a naming context for session bean lookups
7: Context ctx = ejbC.getNamingContext();
8:
9: // Retrieve a reference to the AccountBean using a
10: // portable global JNDI name (more on this later!)
11: AccountBean ab = (AccountBean)
12: ctx.lookup("java:global/account/AccountBean");
13:
14: // Test the account
15:
16: Account a1 = ab.createAccount(1234);
17:
18: ...
19:
20: // Shutdown the embeddable container
21: ejbC.close();
22:
Next we prepare the following three .jars :
- account.jar
An ejb-jar containing the AccountBean class and its associated persistence artifacts. - client.jar
A .jar containing the test client class. - vendor.jar
A vendor-provided .jar file containing the necessary system classes.
All that's left to do is start the JVM using a normal java command :
% java -cp account.jar:client.jar:vendor.jar com.acme.AccountTest
It's important that we support starting the JVM with a plain java command. Not only is it easily understood by developers but it ensures straightforward integration with existing test frameworks and IDEs. We also plan to support an "exploded" directory form of the ejb-jar to reduce the number of packaging steps.
There are more details to work out but we think this is a good first step. As always, let us know your feedback by leaving comments here or by sending email to jsr-318-comments@jcp.org.

Yes! So, when can we try it out? :-)
Posted by Eduardo Pelegri-Llopart on July 29, 2008 at 12:43 PM EDT #
> % java -cp account.jar:client.jar:vendor.jar com.acme.AccountTest
>It's important that we support starting the JVM with a plain java command.
This is a naive example, as in real life it would require tons of jars in the classpath (JUnist/TestNG, many vendor jars, internal project dependencies, etc.). So, it has to be either called by the build script, or by IDE.
> Not only is it easily understood by developers but it ensures straightforward
> integration with existing test frameworks and IDEs. We also plan to support an
> "exploded" directory form of the ejb-jar to reduce the number of packaging steps.
Without exploded deployment, this feature is almost useless, at least productivity-widely speaking. As a developer, I want to right click on my test case in the IDE and do a 'Run as Test Case'. If I have to create a JAR (or rely in my IDE to do it) in order to run the test case, it would still be annoying...
Posted by Felipe Leme on July 30, 2008 at 04:24 PM EDT #
Thanks Eduardo. We're working on it :-)
Posted by Ken Saks on July 31, 2008 at 09:33 AM EDT #
Hi Felipe,
Thanks for the feedback. Valid point that many applications will require many more classpath entries. It's fine if the JVM containing the embeddable usage is called from a script or IDE. The main integration points are still just the contents of the JVM classpath and the classloader at the time createEJBContainer is called. Do you see other issues with that approach? One thing I didn't mention is we're planning to allow the application to programmatically override which modules are initialized.
It's good to hear confirmation of the importance of the exploded directory option.
Posted by Ken Saks on July 31, 2008 at 09:51 AM EDT #
Hey Ken,
My team has been doing a lot of unit testing (with JUnit) of EJB w/ embedded JBoss since EJB3 came out. It is invaluable to the development process and a huge win for EJB3 that this is possible. We can run our unit tests from Eclipse (or other IDE), during builds, or any other time we need to validate functionality.
One big thing is that you need to make sure that you can bring in other resources such as RDBMS's, message queues, transaction managers, etc. These resources are so tightly coupled with your EJBs that effective testing requires them. So while we mostly configure from annotations, some configurations, like queues and database connection information, may be in external files, and in our case is application server specific. These need to be loaded from the classpath as well to get everything working correctly.
Often, prior to making assertions on our EJB, we want to run some SQL to prime the database. This is especially useful if we find a bug in test/production and want to try to replicate it in the unit test. Rather than trying to reproduce the problem programmatically, all we need to do is export the data from the database, add it to our unit test and then do the assertions. Makes it very easy to replicate what would otherwise be tricky bugs to find.
An alternative approach to this would be something like fixtures in Ruby on Rails that get auto-loaded each time you run your test. That approach probably wouldn't work in this sort of specification though.
If you are interested, I gave a presentation a few times on what we did with unit testing EJBs. The presentation can be found at http://www.innovationontherun.com/presentation-files/ete2007-dimarco-java-ee-unit-testing.pdf with associated code at http://www.innovationontherun.com/presentation-files/ete2007-dimarco-java-ee-unit-testing-code.zip
Posted by Rob Di Marco on August 01, 2008 at 09:38 AM EDT #
Thanks for the feedback Rob. It is definitely our goal that it be possible to use these resources within the embeddable container. As you point out, anything less limits the testing benefits. In some cases it will require adding some properties to an overloaded version of the createContainer() API.
Posted by Ken Saks on August 04, 2008 at 11:42 AM EDT #