Sunday, August 29, 2010

Unit testing EJB 3.1 with Derby DB and embedded Glassfish

Unit testing EJBs has always been a bit of a pain as you'd need to deploy them to a container first. This is something that JEE6 addresses by specifying an embeddable implementation of the container. Using the embeddable container is simple enough, but I wanted to unit test an EJB that acted as a façade to a JPA entity backed by a derby database. I've had all sorts of problems getting this going.

I originally tried this based on sample code from chapter 6 of Antonio Goncalve’s book JEE6 with Glassfish 3 which despite being an excellent book, I couldn't get the example working. I've been trying to get the sample going for a little while and followed heaps of different blogs and ideas but was still unsuccessful. Recently I was pointed to this great post which gave me enough info to get it working so I figured I'd re-post the example from Antonio's book with some info so that anyone bashing their head against the same wall as I was could get it running.

Taking the original code from Chapter6 of Antonio’s book it looks something like this:

  • Book.java: a JPA entity that handles storage and retrieval of book data.
  • BookEJB: A Stateless Session bean that invokes the JPA entity to uses it
  • BookEJBTest: A class to test the EJB using JUnit test.
  • persistence.xml: configuration file specifying and persistence units.

The issue with the sample code is that when an instance of the embedded container is created,
it doesn’t successfully find BookEJB to deploy and it doesn’t have any knowledge of the jdbc-resource-pools required for a JTA data source.

The original code for instantiating the embedded container is:
public static void initContainer() throws Exception {
ec = EJBContainer.createEJBContainer();
ctx = ec.getContext();
}
To resolve these issues we need to do a few things:
  • Create a simple glassfish domain with a domain.xml configuration file that contains the relevant jdbc-connection-pools, and jdbc-resources.
  • Additionally, we need to tell the embedded container where to look for this stuff so we replace the original code with some pointers to where to find the classes
To do this, replace the provided initContainer method with the following code.

@BeforeClass
public static void initContainer() throws Exception {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(EJBContainer.MODULES, new File("target/classes"));
properties.put("org.glassfish.ejb.embedded.glassfish.installation.root", "myGlassfish");
properties.put(EJBContainer.APP_NAME, "chapter06");
ec = EJBContainer.createEJBContainer(properties);
ctx = ec.getContext();
}


Specifying the "EJBContainer.MODULES" property tells the embedded container explicitely where to look for EJBs to deploy.

Specifying the "org.glassfish.ejb.embedded.glassfish.installation.root" property, allows the container to find the resource adapters and domain.xml.

When looking up the BookEJB, you need to use the fully qualified name (note the app name 'chapter06' that we specified as a property in the modified code:
BookEJB bookEJB = (BookEJB) ctx.lookup("java:global/chapter06/BookEJB!org.beginningee6.book.chapter06.BookEJB");


Now it’s just a matter of putting the files in the right locations, ensuring your persistence.xml and domain.xml are consistent and the unit test will work...

Assuming you already have the original code (including all chapters etc), unpack the updated code in the same location, run 'mvn clean test' and it should all hang together...

Here's a screen shot of the workspace...