OpenEJB: EJB for Tomcat
Pages: 1, 2
Configuring Tomcat
Tomcat is a servlet container and as such, doesn't host EJBs. That's where OpenEJB comes onto the scene. It's a EJB container. The role of OpenEJB is to create a runtime environment to run EJBs and let others access them in a unified way. Regardless of which application wants to access the beans, they all do it the same way, by accessing the appropriate Java Naming and Directory Interface (JNDI) context and looking up a home object. Think about JNDI as a catalog of names with objects bound to them. JNDI Initial Context is the starting point when working with the catalog--looking up a name or accessing the object bound to it.
This article has been tested under Jakarta Tomcat 4.1.18. Make sure you aren't using the older version.
OpenEJB can run in two modes: Local (AKA IntraVM) Server and Remote Server. The difference is the approach with which they're initialized and then accessed. OpenEJB Local Server requires some OpenEJB-specific .jars to be available in a client's classpath. It will start automatically the first time the JNDI Initial Context is created. The Remote Server must be booted manually. The above command line session demonstrates how this is done for OpenEJB Remote Server. Technically, OpenEJB Local Server is nothing more than OpenEJB Remote Server that doesn't listen on ports, so remote clients cannot connect.
As previously mentioned, Tomcat knows nothing about EJBs other than that it allows them to
be bound in its naming hierarchy, so that JSPs and servlets can access them.
These names are merely names when no EJB container hosts the beans tied to
them. We are about to see the bridge from Tomcat to the OpenEJB runtime
environment. The bridge is an JNDI Object Factory. The factory builds objects
on the fly when they are requested from a naming system. The OpenEJB
TomcatEjbFactory class intercepts bean requests and passes them to OpenEJB.
OpenEJB services the request and responds back appropriately.
If you want to find out more on the TomcatEjbFactory class, read this
document.
Installation of the factory requires some OpenEJB classes to be available for Tomcat. This is accomplished by deploying a simple web application to Tomcat that loads OpenEJB .jars into Tomcat's class path. A sample application ships with OpenEJB. When Tomcat starts, the web application is deployed and the application's loader servlet executes, loading the .jars.
Deploying the web application boils down to deploying openejb_loader-0.9.0.war from the <OPENEJB_HOME>/dist directory to the <CATALINA_HOME>/webapps directory. Tomcat searches this directory for web applications to deploy when it starts.
You can configure the way the web application works. Edit its deployment
descriptor (/WEB-INF/web.xml) and you'll see the configuration
options as <init-param>s of the loader servlet:
openejb.home: the path where OpenEJB is installed.openejb.configuration: the OpenEJB configuration file.openejb.localcopy: is OpenEJB supposed to copy all variables between beans?
Don't forget to uncomment and update openejb.home, or OpenEJB
won't be able to find its classes. Once the value has changed, restart
Tomcat.
The last step is configuring TomcatEjbFactory in Tomcat's
default configuration file (server.xml). EJB name bindings appear
between <Context> elements of the web application whose
components use the bean. The sample EJB binding is shown below.
Place the following declaration between <Context> elements
of Tomcat's examples web application.
<Ejb name="ejb/hello"
type="Session"
home="org.acme.HelloHome"
remote="org.acme.Hello"/>
<ResourceParams name="ejb/hello">
<parameter>
<name>factory</name>
<value>org.openejb.client.TomcatEjbFactory</value>
</parameter>
<parameter>
<name>openejb.naming.factory.initial</name>
<value>org.openejb.client.LocalInitialContextFactory</value>
</parameter>
<parameter>
<name>openejb.naming.security.principal</name>
<value>username</value>
</parameter>
<parameter>
<name>openejb.naming.security.credentials</name>
<value>password</value>
</parameter>
<parameter>
<name>openejb.naming.provider.url</name>
<value>localhost:4201</value>
</parameter>
<parameter>
<name>openejb.ejb-link</name>
<value>Hello</value>
</parameter>
</ResourceParams>
The <Ejb> element and its corresponding
<ResourceParams> declares that the name ejb/hello
points to a session bean whose remote interface is org.acme.Hello, and whose home interface is org.acme.HelloHome.
With the <Ejb> element come <ResourceParams>
parameters. These parameters configure Tomcat to know that whenever the
ejb/hello name is accessed, the factory (of
org.openejb.client.TomcatEjbFactory) should fullfil the request.
Other <parameter>s configure the TomcatEjbFactory
itself, which has to know how to access the OpenEJB server. One of the
<parameter>s is <openejb.ejb-link>, which maps
the name from Tomcat to OpenEJB. These are two separate naming systems. Each
has its own naming space, and the names in one must be linked to their
counterparts in the other.
OpenEJB does not need to be started manually in this configuration. As
indicated by the <openejb.naming.factory.initial> parameter's
value, it will be done automatically. Changing the value to
org.openejb.client.RemoteInitialContextFactory says to connect to
OpenEJB that listens to requests at localhost on port 4201. Assuming you have
not changed the OpenEJB configuration, it listens on port 4201.
You can find more configuration information in the OpenEJB TomcatEjbFactory documentation.
Let's test the configuration. Start up Tomcat and look at the output. You should see something like the following:
> ./bin/catalina.sh run
Using CATALINA_BASE: /disk/home/jacekl/artykul/jakarta-tomcat-4.1.18
Using CATALINA_HOME: /disk/home/jacekl/artykul/jakarta-tomcat-4.1.18
Using CATALINA_TMPDIR: /disk/home/jacekl/artykul/jakarta-tomcat-4.1.18/temp
Using JAVA_HOME: /opt/java1.3
[INFO] Registry - -Loading registry information
[INFO] Registry - -Creating new Registry instance
[INFO] Registry - -Creating MBeanServer
[INFO] Http11Protocol - -Initializing Coyote HTTP/1.1 on port 8080
Starting service Tomcat-Standalone
Apache Tomcat/4.1.18
OpenEJB 0.9.1 build: 20030118-2102
http://openejb.sf.net
[INFO] Http11Protocol - -Starting Coyote HTTP/1.1 on port 8080
[INFO] ChannelSocket - -JK2: ajp13 listening on 0.0.0.0/0.0.0.0:8009
[INFO] JkMain - -Jk running ID=0 time=4/317
config=/disk/home/jacekl/artykul/jakarta-tomcat-4.1.18/conf/jk2.properties
As you might have noticed, OpenEJB has also started while Tomcat was
initializing the example web application's resources. This is because the
factory had been told to boot OpenEJB Local Server via the
openejb.naming.factory.initial parameter. Therefore, in this
configuration, Tomcat will start up OpenEJB as well.
Creating and Deploying the Web Application
Having configured Tomcat and the factory, we are now able to look up
ejb/hello in Tomcat's naming space and expect to get hold of the
Hello EJB deployed in OpenEJB.
This code shows how simple it is. Download it here.
Example 1 -- openejb.jsp
<%@ page import="org.acme.HelloObject,
org.acme.HelloHome,
javax.naming.InitialContext,
javax.naming.Context"%>
<html>
<head>
<title>OpenEJB -- EJB for Tomcat</title>
</head>
<body>
Stateless Session bean - HelloBean - says:
<%
Context initCtx = new InitialContext();
Object object = initCtx.lookup("java:comp/env/ejb/hello");
HelloHome helloHome = (HelloHome)
javax.rmi.PortableRemoteObject.narrow(object, HelloHome.class);
HelloObject bean = helloHome.create();
%>
<%= bean.sayHello() %>
</body>
</html>
Assuming you haven't tweaked Tomcat's configuration too much, save the file in $CATALINA_HOME/webapps/examples. Tomcat's example web applications reside there, and saving the file there shortens the path of deploying a separate web application. (Also, we don't have to learn too much about Tomcat configuration in this article.)
Running the Example
Now it's time to see it working. Start up Tomcat and browse to this URL: http://localhost:8080/examples/openejb.jsp .

Figure 1 -- our application in action
Summary
When EJB is mentioned, a few products come to mind. They usually require some time working with configuration files before they're started up and functioning well, especially when combined with Tomcat. Sometimes it's not possible at all. More importantly, they always require installing another platform on your computer that replaces the standalone Tomcat with some platform where Tomcat is a service of some kind. You won't be happy if you've already invested time learning the standalone Tomcat.
As you might have seen, OpenEJB is quite different. Installation boils down to deploying an OpenEJB web application and setting up Tomcat so that some of the JNDI names point to the OpenEJB naming system. Nothing more than that; no changes to already-deployed web applications, no additional configuration files in Tomcat, and frankly, you won't be tied to a specific Tomcat version. So, do we need more benefits? They're coming ...
If anybody says EJB containers require a lot of time to grasp, mention OpenEJB. The development of OpenEJB is ongoing, so it's possible to see more features pertaining to the integration in the future. Make sure to visit the OpenEJB home page often.
Jacek Laskowski is a technical consultant at Hewlett-Packard. In his spare time, he contributes to OpenEJB development.
Return to ONJava.com.