With the recent introduction of the Java Persistence API (JPA), WebSphere is forging new trails with their JPA solution. Built on top of the Apache OpenJPA
project, the WebSphere JPA solution provides exceptional function, performance, and support. The postings on this site are our own and don’t necessarily represent IBM’s positions, strategies, or opinions.

Monday, March 28, 2011

Recognizing the importance of accelerated development and simplified testing, Enterprise JavaBeans took a page out of the JPA book by including JSE-friendly embeddable container within the EJB 3.1 specification. While the embeddable container doesn't support all the bells and whistles of a full blown container, it gives you plenty of features that can drastically speed up development and more importantly, provide a test environment that more closely resembles a JEE environment - in both configuration and behavior.

The EJB 3.1 specification outlines these features for the embeddable container:

Synchronous calling of local stateless, stateful, and singleton beans (singletons are new in EJB 3.1)

Declarative and programmatic security

Interceptors

Use of annotations or XML deployment descriptors

Support for JPA 2.0

In addition to these features, the embeddable EJB container provided with WebSphere Application Server V8 provides the ability to easily configure JDBC data sources. This is especially important when using JPA in container managed mode. WebSphere's embeddable container even supports the use of JTA component data sources within your persistence.xml. This allows you to use the same persistence.xml with the embeddable container as you use in your enterprise application.

With the exception of an optional (but recommended) IDE such as Eclipse or RAD 8.0.3, WebSphere Application Server V8 contains everything you need to get started - the Java SDK (depending on platform), the embeddable container, JPA client package, and the Derby database. When you install the beta be sure to install Stand-alone thin clients, resource adapters and embeddable containers.

For the purposes of an example, let's say we have a simple EJB module that is used to manage personal contacts. The ContactModule contains a simple annotated session bean named ContactBeanwhich is primarly a transactional facade over JPA operations. The operations provided by the EJB allow you to find a contact by name, save a contact, and clear all contacts. The JPA operations operate on a persistent entity, Contact. TheContactBean is a session bean that implements a local interface ContactLocal. While EJB 3.1 will now provide access to an bean without a Local interface, using interfaces is still a good practice. Interfaces provide a layer of abstraction from the base bean. They allow the bean to implement multiple specialized interfaces or allow the client to call a different EJB which implements the interface without modifying Java code. Here are our EJB and JPA classes and persistence.xml:

The simple EJB + JPA module looks like this when loaded as an Eclipse project:

Since ContactModule uses only Java EE APIs, it only requires WAS_HOME\dev\JavaEE\j2ee.jar to compile. If you use WebSphere, OpenJPA, or other extensions you'll need to include additional jars in your build path. Remember, this is only to compile the EJB + JPA module. We'll need different jars to actually run the module in the Embeddable EJB Container.

Now that the module is defined, we need to create an EJB jar file. As of EJB 3.0, a deployment descriptor (ejb-jar.xml) is not required. You can either use the "jar" command to create the jar or use the Eclipse Export... -> Java -> JAR file wizard. Export the jar to a location such as C:\ContactModule.jar. The EJB jar file should contain:

META-INF/MANIFEST.MF

entities/Contact.class

ejbs/ContactBean.class

ejbs/ContactLocal.class

META-INF/persistence.xml

We now have an EJB module. Traditionally, to test this module you'd write a web client, deploy it in the app server, and drive some http operations against it. Another option is to create a JEE client container app and then drive the EJB using launchClient. Or you may have used RAD's Universal Test Client to execute EJB operations. All of these options work, but they can be difficult to automate and some of them may require code modifications in order to work properly.

Let's take a look at how the Embeddable EJB Container can be used to simplify this testing using the popular JUnit 4 test framework. Again, I used an Eclipse project, but provided that you have the necessary JUnit 4 libraries, you can also run the same tests from the command line. To test the basic functions of our ContactBean session bean, we'll create a simple JUnit 4 annotated test class, TestContactBean.

If you've used JPA in JSE-mode, the pattern looks pretty familiar, right? We use a static EJBContainer.createEJBContainer() method to create the embeddable container and then use a lookup to get an instance of the bean. Knowing what JNDI name to use can be a little tricky, but the new java:global namespace simplifies that as well. In general, you can use java:global/module-name/bean-name[/!interface] to look up the bean. After you have a reference to the bean, you can call its EJB methods. Piece of cake. Well there is a little more to do. In order to get the code to compile and run you need to include ContactModule.jar, WAS_HOME\runtimes\com.ibm.ws.ejb.embeddableContainer_8.0.0.jar, WAS_HOME\runtimes\com.ibm.ws.jpa.thinclient_8.0.0.jar, and the jUnit jars in your classpath.

If we were simply testing EJBs we'd be all set. JPA has a few more requirements we need to take care of. First, since we'll be using Derby as our database, we need to add the Derby library to our classpath. It can be found at WAS_HOME\derby\lib\derby.jar. Second, in an EE environment, JPA uses data sources to connect to a relational database. JPA typically requires both a transactional and non-transactional data source. WebSphere's embeddable container allows us to very easily configure data sources one of two ways. The most flexible of the two approaches is to configure them within a properties file. If a file named embeddable.properties is found on the classpath the properties in this file will automatically get loaded by the embeddable container . The WebSphere Embeddable EJB Container also allows you to pass properties in via Map on the createEJBContainer method. As a third option you can specify a system property to inform the embeddable container where its properties file resides. More information on the properties supported by the embeddable container can be found in the Information Center article Embeddable EJB container configuration properties. You'll find that the embeddable container is extremely configurable. You can even configure settings such as cache size, security options, and logging.

As you can see, using @DataSourceDefinition is a very simple way to define data sources. There is no properties file or @Resource references to manage. The data sources automatically get registered into the java:comp/env namespace (take a look jta-data-source and non-jta-data-source definitions in the persistence.xml - as a best practice, component data sources are used). However, simplicity comes at the cost of flexibility. A change in the data source definition requires recompiling the application.

There's one more JPA-specific item we need to take care of before running the test. In the full application server, the container takes care of JPA entity enhancement. This does not occur in the embeddable container. Fortunately, you can either enhance the entities at build time or the JPA agent-based enhancer can be used to perform the enhancement at runtime. Enabling the enhancer is as simple as specifying the JVM option -javaagent:C:\/"Program Files/"\IBM\WebSphere\AppServer\runtimes\com.ibm.ws.jpa.thinclient_8.0.0.jar on the java or Eclipse jUnit invocation. If all goes well, you should see a result similar to this...