One of the hardest steps for beginning J2EE developers to take is to build their first EJBs. This article will set aside those fears and help you venture into the world of EJB development.
If you’re not yet sure what EJBs are or why you should consider them for a particular project, be sure to read Part 1 of this primer.
Installing the J2EE SDK
In order to build and run an EJB, you must install a J2EE-compliant EJB container. The reference implementation EJB container can be found in the J2EE development kit that’s obtainable from Sun. You can download the latest version from http://java.sun.com/j2ee.
The J2EE development kit depends on the Java 2 SDK, Standard Edition (J2SE) development kit, so you will need to download it as well. You can find it at http://java.sun.com/j2se/index.html. You need the J2SE SDK to run the J2EE server and to build and run J2EE applications.
Once you have downloaded the development kits, install them and select the desired location for each kit. Define an environment variable named JAVA_HOME and point it to the install directory for the J2SE development kit. Next, define an environment variable named J2EE_HOME and point it to the install directory for the J2EE development kit.
Now, you’re ready to begin writing your EJB.
Writing a Session Bean
Developing an EJB involves most of the same steps and concepts that you have become familiar with when developing plain old Java objects (POJOs), with a few minor differences. The following steps illustrate the typical process to develop and deploy an EJB:
- Write the classes and interfaces for your enterprise bean
- Write a deployment descriptor
- Package the enterprise bean and associated files inside of a jar file
- Deploy the bean
Before we get into the gory details of writing our bean, let’s look again at the two different types of session beans.
A Recap of Stateful Session Beans
A stateful session bean maintains a conversational state with one client for the duration of a single session. This implies that the stateful session bean can maintain instance variables across multiple invocations from one client during a single session.
Once the client finishes interacting with the enterprise bean and the EJB container removes the enterprise bean, the session for the bean ends and all state data for the bean is discarded.
A Recap of Stateless Session Beans
A stateless session bean does not maintain a conversational state for each individual client. Each invocation of a stateless session bean should be considered as a request to a brand new object instance, since any instance-variable state will be lost between invocations.
Stateless session beans are not persisted to secondary storage by the EJB container; therefore a programmer must recognize that all data is transient between invocations for each client. The transient nature of stateless session beans allows an EJB container to reuse bean instances and, therefore, usually optimize the performance of the beans.
Session Bean Relationships
Figure 1 illustrates the relationships that exist between an EJB client, an EJB container, and a couple of session beans:
Figure 1
A session bean is composed of a minimum of three mandatory classes/interfaces. The first mandatory class/interface is the Component interface, and it must extend javax.ejb.EJBObject. We will implement a very simple stateless session bean that returns a short String message from a method named “retrieveMessage”.
The code for our Component interface is as follows:
package com.jeffhanson.ejb;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
public interface SimpleMessenger extends EJBObject
{
public String retrieveMessage() throws RemoteException;
}
The second mandatory class/interface is the Home interface, and it must extend javax.ejb.EJBHome. The code for our Home interface is as follows:
package com.jeffhanson.ejb;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
public interface SimpleMessengerHome extends EJBHome
{
SimpleMessenger create() throws RemoteException, CreateException;
}
The third mandatory class/interface is the Enterprise Bean class, and it must implement the javax.ejb.SessionBean interface. The code for our Enterprise Bean class is as follows:
package com.jeffhanson.ejb;
import java.rmi.RemoteException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
public class SimpleMessengerBean
implements SessionBean
{
private SessionContext sessionCtx = null;
public String retrieveMessage()
{
return "Hello from SimpleMessengerBean ";
}
public void ejbCreate()
{
}
public void ejbRemove()
{
}
public void ejbActivate()
{
}
public void ejbPassivate()
{
}
public void setSessionContext(SessionContext sessionCtx)
{
this.sessionCtx = sessionCtx;
}
}
Compiling a Session Bean
An EJB is compiled in the same manner as a POJO, using the javac compiler, and, as with a POJO, you must make sure the appropriate class files are found on your classpath. The EJB class files are part of the javax.ejb package and can be found in the j2ee.jar file within the lib directory of J2EE reference implementation’s install path.
The following command-line will compile the classes and interfaces that we have defined for our EJBs:
javac -classpath <J2EE_HOME>/lib/j2ee.jar -d <output directory> *.java
You must replace <J2EE_HOME>
and <output directory>
with the path where you installed the J2EE reference implementation and the directory where you’d like to place your newly-compiled class files, respectively.
In order for EJBs and EJB clients to communicate, the proxy classes used by the EJB communication protocol — typically REmote Method Invocation (RMI) — must be generated. These proxy classes are known on the client-side as stubs and on the EJB-side as skeletons. To generate the stubs and skeletons, we must run our classes and interfaces through a utility that will generate the communication details for the particular protocol we’re planning to use. As we’ll use RMI as the communication protocol, we can use the rmic tool that ships with the J2SE installation. The following command illustrates the use of this tool to compile our remote classes:
<JAVA_HOME>binrmic.exe -d <output directory> -classpath <JAVA_HOME>jrelibrt.jar;<J2EE_HOME>libj2ee.jar -sourcepath <source directory> com.jeffhanson.ejb.SimpleMessengerHome com.jeffhanson.ejb.SimpleMessenger
Deploying a Session Bean
Once you’ve written and compiled the source code for your session bean, you must deploy it into the EJB container’s environment. This involves describing your EJB type, your desired transaction type, the EJB’s home class, the EJB’s remote class, and other information. The deployment descriptor is used to contain these descriptions.
The Deployment Descriptor
To deploy an EJB into an EJB container’s environment, you must supply a deployment descriptor file to the EJB container. A deployment descriptor file is an XML document, named ejb-jar.xml, that specifies information about the bean such as its persistence type and transaction attributes. An EJB’s class files and deployment descriptor must be packaged into a JAR or EAR file.
The following is an example of a deployment descriptor for our session bean:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar>
<description>A simple session bean</description>
<display-name>Simple Message EJB</display-name>
<enterprise-beans>
<session>
<ejb-name>SimpleMessenger</ejb-name>
<home>com.jeffhanson.ejb.SimpleMessengerHome</home>
<remote>com.jeffhanson.ejb.SimpleMessenger</remote>
<ejb-class>com.jeffhanson.ejb.SimpleMessengerBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Bean</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
If this seems like a lot of minutiae to fuss with, don’t despair; we’ll find a helpful utility to ease our job in a moment. In the meantime, let’s look at how we ready the environment in which we will deploy our EJB.
Starting the EJB Container
Once you’ve written and compiled your EJB, you must deploy it into an EJB-container’s environment. This typically means installing the EJB into an application server’s environment. We will deploy our session bean into the environment of the EJB container that ships with the J2EE reference implementation’s server.
To start the J2EE reference implementation’s server, run the script file j2ee.bat (j2ee.sh on Unix/Linux), which is found in the <J2EE_HOME>bindirectory. This will start the server listening to HTTP requests on port 8000. To test the server, point your HTML browser to http://localhost:8000. You should see something that resembles the page in figure 2.
Figure 2
Using the Deployment Utility
We will use the deployment utility deploytool that is installed with the J2EE reference implementation to package and deploy our EJB. To launch the deploytool, run the deploytool.bat or deploytool.sh script file found in the <J2EE_HOME>bin directory. This will start deploytool in GUI mode and allow us to visually see our EJB being packaged and deployed. The main page of deploytool looks something like figure 3.
Figure 3
Creating the J2EE Application
In order to deploy an EJB into an application server’s environment, you must create an application for the EJB to live in. To create a new J2EE application in deploytool:
- Select the File->New->Application menu item.
- Click the Browse button and locate the directory where you want the application to be created. For now, choose the <J2EE_HOME>public_html directory.
- Enter EJBTest in the File Name box, click the New Application button, then click the OK button.
Now that we have created our application, we can package our session bean and add it to the application.
Packaging the Enterprise Bean
We will use deploytool to package our EJB and add it to our EJBTest application.
- In deploytool, select the File->New-> Enterprise Bean… menu item. This starts the New Enterprise Bean Wizard.
- Press the Next button on the Introduction page, and make sure the Create New JAR File in Application radio button is selected and EJBTest is selected as the application. In the JAR Display Name box, enter SimpleMessenger.
- Press the Edit button to the right of the Contents text box. This will launch a new dialog. In this dialog, navigate to the directory that contains your class files, select all of the .class files and press the Add button. Then press the OK button.
This should leave you with a page that resembles figure 4.
Figure 4
Now, press the Next button. On the next page:
- Select the Session radio button and the Stateless radio button.
- Select SimpleMessengerBean in the Enterprise Bean Class box, SimpleMessengerHome in the Remote Home Interface box and SimpleMessenger in the Remote Interface box. This should leave you will a page that resembles figure 5.
Figure 5
At this point, press the Next button and then the Finish button on the next page.
Deploying the J2EE Application
Once you’ve packaged your EJB and added it to the EJBTest application, you can deploy the EJB into the application server. The following steps describe how to do this in deploytool:
- Select the EJBTest application in the navigation pane of deploytool. Select the JNDI Names tab and in the JNDI Name field enter SimpleMessenger and press the Enter key.
- Select the Tools->Deploy . . . menu item. On the first page, make sure that the Object to Deploy is set to EJBTest and the Target Server is set to localhost. Select the Return Client Jar checkbox and then press the Next button.
- On the JNDI Names page, press the Next button and then press the Finish button.
- On the Review page, press the Finish button.
- The deployment process will begin and you will be able to see the progress. When the deployment process is finished, press the OK button.
Now, you can look in the <J2EE_HOME>public_html directory to find two jar files; EJBTest.jar and EJBTestClient.jar.
Your EJB is now deployed and ready to access from clients. We’ll discuss the mechanisms for accessing EJBs from client applications in another article.
Summary
One of the hardest steps for beginning J2EE developers to take is to build their first EJBs. This article attempted to assuage those fears and help you venture into the world of EJB development.
In order to build and run an EJB, you must install a J2EE-compliant EJB container. The reference implementation EJB container can be found in the J2EE development kit from Sun.
Developing an EJB involves most of the same steps and concepts that you have become familiar with when developing plain old Java objects (POJOs), with a few minor differences. The steps involved in developing and deploying an EJB are:
- Write the classes and interfaces for your enterprise bean
- Write a deployment descriptor
- Package the enterprise bean and associated files inside of a jar file
- Deploy the bean
A session bean is composed of a minimum of three mandatory classes/interfaces: the Component interface, the Home interface, and the Enterprise Bean class.
An EJB is compiled in the same manner as a POJO, using the javac compiler, however, for EJBs and EJB clients to communicate, the proxy classes used by the EJB communication protocol (typically RMI) must be generated. These proxy classes are known on the client-side as stubs and on the EJB-side as skeletons.
Once you have written and compiled the source code for your session bean, you must deploy it into the EJB container’s environment. This involves describing your EJB type, your desired transaction type, the EJB’s home class, the EJB’s remote class, and other information. The deployment descriptor is used to contain these descriptions. A deployment descriptor file is an XML document, named ejb-jar.xml, that specifies information about the bean such as its persistence type and transaction attributes.
Once you have written your EJB, compiled your EJB you must package and deploy it into an EJB-container’s environment. This typically refers to deploying the EJB into an application server’s environment. The J2EE reference implementation’s deploytool is very useful for creating applications and for packaging and deploying EJBs.
Jeff has more than 18 years of experience in the software development industry, including almost 7 years experience with Java and J2EE. He's authored numerous articles and books, including NET versus J2EE Web Services: A Comparison of Approaches and Connecting JMX Clients and Servers: Understanding the Java Management Extensions.