ONJava.com    
 Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples


OpenEJB: EJB for Tomcat

by Jacek Laskowski
02/12/2003

There has probably been a day in your life when you've asked yourself if your web application might use other J2EE concepts besides Java servlets. Your dilemma has most likely been "Although I could read the specifications, I don't have time to set up the containers and enhance the application."

In most cases, that's what keeps people away from leveraging J2EE technologies in their applications. It happens with other architectures, too. However, this doesn't have to last forever, as there are tools to make your life easier. OpenEJB is one--you can run it with no problems after having spent a few minutes reading a quick introduction.

Before we delve into the topic, I'd like to mention that you can find out more details about OpenEJB at the OpenEJB home page.

OpenEJB allows you to use EJBs in your applications with very few configuration files and commands. After reading this article, you will be able to use EJB as you might have been using JDBC with databases like HSQL or Cloudscape. You won't have to spend a lot of your precious time to configure and run an application server. Merely deploy a simple web application from OpenEJB distribution and map the beans deployed in OpenEJB to their respective names in Tomcat's naming system.

Related Reading

Enterprise JavaBeans
By Richard Monson-Haefel

OpenEJB can run in two server modes--local (AKA IntraVM) and remote. The main difference between them is the address space (or JVM) in which they run. OpenEJB Local Server runs in the same JVM as the application that uses it. On the other hand, OpenEJB Remote Server runs within its own JVM, probably on a different server than the client application.

The aim of this article is to present an easy yet powerful way of combining Tomcat with OpenEJB so that a web application deployed in Tomcat becomes an OpenEJB client in a fully J2EE-compliant manner. You shall see an EJB example deployed into OpenEJB and accessed by a JSP as part of a web application deployed into Tomcat. I don't want you write the EJB and web application, thus the article provides these components in a downloadable form. We'll concentrate on architecture instead.

I think you'll be amazed at how fast and easy is to enhance your web application with OpenEJB. Home and remote interfaces, stubs, and skeletons will not frighten you anymore!

Getting and Installing OpenEJB

Needless to say, before we start working with OpenEJB, it needs to be installed on your system. Download OpenEJB. Be sure to define to define the OPENEJB_HOME environment variable to point to the directory where OpenEJB is installed. After that, let's try it out and see how OpenEJB responds.

> cd $OPENEJB_HOME
> ./openejb.sh start  
--------------SUPPORT INFO-------------
HP-UX B.11.00 A
Using JAVA_HOME:     /opt/java1.4
Using OPENEJB_HOME:  /disk/home/jacekl/artykul/openejb-0.9.1
.
OpenEJB Remote Server 0.9.1    build: 20030118-2102
http://openejb.sf.net
----------------STARTUP----------------
[init] OpenEJB Container System
[init] OpenEJB Remote Server
  ** Starting Services **
  NAME             IP              PORT
  ejb server       127.0.0.1       4201
  admin console    127.0.0.1       4200
-----------------INFO------------------
To log into the admin console, telnet to:
 telnet 127.0.0.1 4200
---------------------------------------
Ready!

This means everything is indeed "Ready" to go. Press Ctrl-C to stop the session.

Deploying Hello World EJB

The code outlined here will not differ in any way from what you might have seen at the OpenEJB pages. It's a simple stateless session bean with a business method--sayHello(). The JSP will call this method. Download the bean's .jar.

Deploying the bean is easy. Invoke the following command under Cygin or any other Unix-like system:

> cd $OPENEJB_HOME
> ./openejb deploy -a -f -c <the jar location>

The options given on the command line above are to automate deployment as much as possible (the -a option) and forcefully (the -f option) and to copy (the -c option) the .jar to the OPENEJB_HOME/beans directory, overwriting any previously existing .jar with the same name.

Run the following command to get acquainted with the deploy options:

> ./openejb.sh deploy

When deploying the Hello bean, you shall see the following output:

> ./openejb.sh deploy -a -f -c ~/myHelloEjb.jar 
--------------SUPPORT INFO-------------
HP-UX B.11.00 A
Using JAVA_HOME:     /opt/java1.4
Using OPENEJB_HOME:  /disk/home/jacekl/artykul/openejb-0.9.1
.
OpenEJB Deploy Tool 0.9.1    build: 20030118-2102
http://openejb.sf.net

This jar contains the following beans:
  Hello


-----------------------------------------------------------
Deploying bean: Hello
-----------------------------------------------------------

==--- Step 1 ---==

Auto assigning the ejb-name as the deployment id for this bean.

Deployment ID: Hello
==--- Step 2 ---==

Auto assigning the container the bean will run in.

Container: Default Stateless Container

-----------------------------------------------------------
Done collecting deployment information!
Creating the openejb-jar.xml file...done
Writing openejb-jar.xml to the jar...done

Congratulations! Your jar is ready to use with OpenEJB.

If the OpenEJB remote server is already running, you will
need to restart it in order for OpenEJB to recognize your bean.

NOTE: If you move or rename your jar file, you will have to
update the path in this jar's deployment entry in your 
OpenEJB config file. 

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:

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.

Copyright © 2009 O'Reilly Media, Inc.