OpenEJB 3 and Tomcat 6
A step by step how-to for embedding the OpenEJB container into Tomcat so that your web applications can use EJB 3 from servlets.
OpenEJB is an embeddable EJB container and server. You can embed OpenEJB in your own applications or in a web application server, such as Tomcat 6 or run it as a standalone EJB server. It's actually been around for 7 years and has recently graduated from incubation at Apache. When I last wrote a step by step tutorial for a user group in late 2003, OpenEJB was at version 0.9.2. At the time it supported only EJB 1.1 and part of the EJB 2 spec. It then seemed to have languished at 0.9.2 for years but what happened was that internally there was a OpenEJB v2 equivalent which became the EJB container for Geronimo 1.0.
Then in early 2006 Open EJB 1.0 was released completing the 0.9.2 "branch", while work continued on the EJB 3 version. The now aptly named OpenEJB 3.x release (version number follows the EJB spec version) is not only the EJB 3 container of Geronimo 2.x (which has been recently JEE 5 certified), it's available on its own again with the original goals and features: allowing you to embed a EJB container (now EJB 3 compliant) with your applications. A more thorough history and interview with OpenEJB co-founder David Blevins is available at IBM's Developer Works and a list of the new features at http://openejb.apache.org/new-in-openejb-30.html.

Edit an EJB bean on a live deployed web app running in Tomcat on any IDE.
A reason to use OpenEJB 3 and Tomcat is for testing EJBs even if you're eventually deploying to a different JEE server (there's even the ability to change the JNDI naming scheme to help with that). But it really goes beyond unit testing, it simplifies the learning (and teaching) of EJB 3. Instead of having to deal with specific JEE app server configuration, packaging and deployment details, you can focus on coding and testing EJBs just as easily as servlets in web applications.
As some may have noticed, most of the current crop of EJB 3 books supply ant build files that are usually for a specific app server or even platform, following the usual build-deploy cycle. And by the time they're in print, configuration issues abound due to JEE server revisions and updates. Developers already familiar with war files and Tomcat can postpone packaging and deployment issues and focus on starting to use EJBs right away in their current web applications. And another reason is to provide a migration path to JEE 5 by using OpenEJB in their current Tomcat based environments (OpenEJB still supports EJB 2.x ).
JBoss now has an embeddable EJB container as well, although that solution is relatively new compared to OpenEJB (please note I have not evaluated JBoss's solution yet). Also on the horizon for Glassfish (by next JavaOne 2008 as I understand) is a modularized JEE stack that could also include a pluggable EJB container.
Although it may seem that OpenEJB 3.x is currently a beta release, from a EJB3 spec point of view it's ready for use (certified via Geronimo's JEE 5 certification).
First go to http://openejb.apache.org/download.html and download the Tomcat integration plugin: openejb.war
This is currently OpenEJB 3.0 beta 1, but if you want tthe bleeding edge you can build the code from source to get the latest features, otherwise skip ahead to the steps below.
Steps:

OpenEJB's web administrator running in Tomcat
Example:
The following code snippets are from an example application consisting of a servlet, a session bean and entities (using JPA with JTA transaction type) and illustrates the use of EJB 3 annotations including: @EJB, @Stateless, @Entity, @PersistanceContext, @OneToOne, @OneToMany, @ManyToOne, @NamedQueries, @JoinColumn.
stateless session bean that manages persistance:
one of the entities representing a line item:
the servlet with the injected session bean:
This web app, ejb3example, mimics the creation of customer orders from a servlet (no html or jsp pages here, just a servlet) and an order is placed every time you access the servlet at http://127.0.0.1:8080/ejb3example/order You can download and deploy this example's war file here: ejb3example.war (source included). As an exercise for those new to EJB 3, add another servlet to query for a specific customer's orders (or all orders if none specified): http://127.0.0.1:8080/ejb3example/query?email=
To change db from the default hsqldb, see conf/openejb.xml.
To run this in an IDE without using the catalina.sh/bat script or the startup scripts, specify the following "Run" configuration parameters:
Additional Notes:
If you're running a plugin or IDE tool that manages it's own copy of Tomcat's server.xml, e.g. Eclipse's "Servers" (another reason why you should use the Run dialog instead) then add the OpenEJB Listener to the top of server.xml (next to the other listeners) :
<Listener className="org.apache.openejb.loader.OpenEJBListener" />
Lastly, you can avoid deploying (bullding war files) and use your project workspace as the deployed folder in Tomcat by adding the following context file to Tomcat's conf/Catalina/localhost folder (while Tomcat is stopped). ejb3example.xml:
Conclusion:
For those bruised by EJB 2.x and earlier or if you're new to JEE (lucky you) or are planning to migrate to JEE 5, then using an embedded EJB container such as OpenEJB 3.x makes it easy to develop and test your EJB 3 apps and allows those already developing on existing JEE 5 environments to more readily develop and test without those build+deploy cycles.
Special thanks to David Blevins and Dain Sundstrom and of course the rest of the OpenEJB development team.
Then in early 2006 Open EJB 1.0 was released completing the 0.9.2 "branch", while work continued on the EJB 3 version. The now aptly named OpenEJB 3.x release (version number follows the EJB spec version) is not only the EJB 3 container of Geronimo 2.x (which has been recently JEE 5 certified), it's available on its own again with the original goals and features: allowing you to embed a EJB container (now EJB 3 compliant) with your applications. A more thorough history and interview with OpenEJB co-founder David Blevins is available at IBM's Developer Works and a list of the new features at http://openejb.apache.org/new-in-openejb-30.html.

Edit an EJB bean on a live deployed web app running in Tomcat on any IDE.
A reason to use OpenEJB 3 and Tomcat is for testing EJBs even if you're eventually deploying to a different JEE server (there's even the ability to change the JNDI naming scheme to help with that). But it really goes beyond unit testing, it simplifies the learning (and teaching) of EJB 3. Instead of having to deal with specific JEE app server configuration, packaging and deployment details, you can focus on coding and testing EJBs just as easily as servlets in web applications.
As some may have noticed, most of the current crop of EJB 3 books supply ant build files that are usually for a specific app server or even platform, following the usual build-deploy cycle. And by the time they're in print, configuration issues abound due to JEE server revisions and updates. Developers already familiar with war files and Tomcat can postpone packaging and deployment issues and focus on starting to use EJBs right away in their current web applications. And another reason is to provide a migration path to JEE 5 by using OpenEJB in their current Tomcat based environments (OpenEJB still supports EJB 2.x ).
JBoss now has an embeddable EJB container as well, although that solution is relatively new compared to OpenEJB (please note I have not evaluated JBoss's solution yet). Also on the horizon for Glassfish (by next JavaOne 2008 as I understand) is a modularized JEE stack that could also include a pluggable EJB container.
Although it may seem that OpenEJB 3.x is currently a beta release, from a EJB3 spec point of view it's ready for use (certified via Geronimo's JEE 5 certification).
Here are the steps for embedding OpenEJB for access from Tomcat web apps:
First go to http://openejb.apache.org/download.html and download the Tomcat integration plugin: openejb.war
This is currently OpenEJB 3.0 beta 1, but if you want tthe bleeding edge you can build the code from source to get the latest features, otherwise skip ahead to the steps below.
| Building OpenEJB3: Click on the Source Code link on the left menu you'll find the directions on how to build OpenEJB 3. You'll need svn and maven (or just maven, but I prefer using svn to check out code). Check out openejb3: $ svn co http://svn.apache.org/repos/asf/openejb/trunk/openejb3 (use https if you run into errors) cd into openejb3 and build: (it won't install anything outside of the openejb3 folder) $ mvn -up -Dmaven.{test,itest}.skip -Dassemble clean install Note the change I made to the above line (compared to the instructions at the site): I used "-up" instead of "-o" (you can't be offline initially anyway) "-up" will upgrade plugins if necessary. Most of the issues I initially encountered with building were dependency related in the maven repository. So basically if you are continually having problems building, try clearing out the apache plugins in the repository located in your home directory: ~/.m2/repository/org/apache/plugins or clear out the entire repository altogether which usually solves any issues with dependencies. Once you've successfully built OpenEJB you will have built the snapshot files for Tomcat located at openejb3/assembly/openejb-tomcat/target/ Rename the openejb-tomcat-3.0.0-SNAPSHOT.war file to openejb.war |
Steps:
- Install the OpenEJB3 Tomcat plugin (deployed as the webapp, openejb.war) by copying it to your Tomcat webapps folder (and start Tomcat if you haven't already).
- Run the installer servlet at http://127.0.0.1:8080/openejb/installer (and press the install button). Note: this will modify your catalina.sh or catalina.bat files required for the OpenEJB3-Tomcat plugin. So this won't work if you're not using those startup scripts, e.g. running Tomcat from your IDE requires extra steps that I'll describe below.
- As indicated, restart Tomcat for these changes to take effect (primarily the change consists of adding a java agent to support OpenJPA).

OpenEJB's web administrator running in Tomcat
Example:
The following code snippets are from an example application consisting of a servlet, a session bean and entities (using JPA with JTA transaction type) and illustrates the use of EJB 3 annotations including: @EJB, @Stateless, @Entity, @PersistanceContext, @OneToOne, @OneToMany, @ManyToOne, @NamedQueries, @JoinColumn.
stateless session bean that manages persistance:
@Stateless
public class OrderManager implements OrderManagerLocal, OrderManagerRemote {
@PersistenceContext(name="ejb3example")
private EntityManager em;
public Object mergeEntity(Object entity) {
return em.merge(entity);
}
public Object persistEntity(Object entity) {
em.persist(entity);
return entity;
}
public List<Customer> queryCustomerFindAll() {
return em.createNamedQuery("Customer.findAll").getResultList();
}
...
one of the entities representing a line item:
@Entity
@NamedQuery(name = "OrderItem.findAll", query = "select o from OrderItem o")
@Table(name = "CUSTOMER_ORDER_ITEMS")
public class OrderItem implements Serializable
{
@Id
@Column(nullable = false)
@GeneratedValue(strategy=GenerationType.SEQUENCE)
private int id;
@ManyToOne(cascade=CascadeType.MERGE)
@JoinColumn(name = "ORDER_ID", referencedColumnName = "ID")
private Order order;
@OneToOne
@JoinColumn(name = "PRODUCT_ID", referencedColumnName = "ID")
private Product product;
...
the servlet with the injected session bean:
@EJBand the META-INF/persistence.xml file:
private OrderManagerLocal manager;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = new PrintWriter(response.getOutputStream());
response.setContentType("text/plain");
List<Product> productlist= manager.queryProductFindAll();
if(productlist.isEmpty()) {
productlist=fillProducts();
for(Product product:productlist) {
manager.persistEntity(product);
}
}
out.println("Customer Order Simulation:\n");
...
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="ejb3example" transaction-type="JTA">
<jta-data-source>
java:openejb/Connector/Default JDBC Database
</jta-data-source>
<non-jta-data-source>
java:openejb/Connector/Default Unmanaged JDBC Database
</non-jta-data-source>
<properties>
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
</properties>
</persistence-unit>
</persistence>
This web app, ejb3example, mimics the creation of customer orders from a servlet (no html or jsp pages here, just a servlet) and an order is placed every time you access the servlet at http://127.0.0.1:8080/ejb3example/order You can download and deploy this example's war file here: ejb3example.war (source included). As an exercise for those new to EJB 3, add another servlet to query for a specific customer's orders (or all orders if none specified): http://127.0.0.1:8080/ejb3example/query?email=
To change db from the default hsqldb, see conf/openejb.xml.
To run this in an IDE without using the catalina.sh/bat script or the startup scripts, specify the following "Run" configuration parameters:
Main class: org.apache.catalina.startup.BootstrapAnd to compile the application, add the following jars to your project's classpath unless JEE support is already available for your IDE project: from Tomcat's /lib: servlet-api.jar, from openejb's /lib: geronimo-ejb_3.0_spec-1.0.jar, geronimo-jpa_3.0_spec-1.1.jar
Working directory: (your Tomcat home folder)
VM arguments: -javaagent:webapps/openejb/lib/openejb-javaagent-3.0-beta-1.jar
Program arguments: start
add to the runtime classpath: [tomcat folder]/bin/bootstrap.jar
Additional Notes:
If you're running a plugin or IDE tool that manages it's own copy of Tomcat's server.xml, e.g. Eclipse's "Servers" (another reason why you should use the Run dialog instead) then add the OpenEJB Listener to the top of server.xml (next to the other listeners) :
<Listener className="org.apache.openejb.loader.OpenEJBListener" />
Lastly, you can avoid deploying (bullding war files) and use your project workspace as the deployed folder in Tomcat by adding the following context file to Tomcat's conf/Catalina/localhost folder (while Tomcat is stopped). ejb3example.xml:
<Context path="/ejb3example" docBase="/workspace/ejb3example" reloadable="true">
</Context>
Conclusion:
For those bruised by EJB 2.x and earlier or if you're new to JEE (lucky you) or are planning to migrate to JEE 5, then using an embedded EJB container such as OpenEJB 3.x makes it easy to develop and test your EJB 3 apps and allows those already developing on existing JEE 5 environments to more readily develop and test without those build+deploy cycles.
Special thanks to David Blevins and Dain Sundstrom and of course the rest of the OpenEJB development team.
Re: OpenEJB 3 and Tomcat 6
I got really excited when I read this. But my excitment was short lived. Yes, the integration of Tomcat 6 and OpenEJB works. However, if you have Tomcat 6 integrated with JAX-WS 2.1, then you will run into class loading problems. I copied all JAX-WS 2.1 libraries in $TOMCAT_HOME/endorsed folder and the JAXB libraries of JAX-WS (newer), conflict with JAXB libraries of openejb/lib (older). Bummer, as of now, I cannot have both openjb and JAX-WS.