JAVA STEP BY STEP
Summary
Enterprise JavaBeans gives us the perfect excuse to revisit our Forum application. EJB's ability to handle messy infrastructure issues will help us quickly replace the current RMI backend with a session bean that provides the same functionality. Because it will use the EJB container's communications, scalability, and transactions support, the ForumSessionServerBean will be surprisingly simple to write. (3,200 words)
By Michael Shoffner
Enterprise JavaBeans (EJB)
1.0 is the exciting new enterprise component model for Java. EJB is exciting because it
brings modern, powerful capabilities to enterprise middleware written in Java.
No longer do you need to write every bit of infrastructure for the middleware tier of a Java application or (if you're lucky) modify previous code for this purpose. Instead, EJB handles that process for you -- all you have to do is write the actual business logic you are trying to implement.
In this article, we'll see how EJB is able to work such miracles. We'll begin with a brief background on the component software model, then we'll zero in on EJB itself. Once you have your bearings, we'll revisit the Forum application of columns past (see Resources for links to all previous Step by Step columns) and port its middleware tier to an enterprise bean.
The component software model
The component software model is based on the idea of creating reusable components that
plug into containers. This model is rapidly gaining popularity in the software development
community because it addresses several important development goals: reuse, high-level
development focus, development automation via tools, and simplified deployment. JavaBeans,
EJB, and ActiveX/COM are examples of component models.
Component models come in two basic flavors -- client-side and enterprise. Client-side component models such as JavaBeans are specialized to handle presentation and user interface issues. Enterprise component models such as EJB are concerned with providing infrastructure for transactions-oriented middleware components.
Using one of the component model specs, component developers write component "building blocks" that implement business logic. Application developers hook up these pre-built components into finished applications, which may themselves be components.
This building block approach facilitates off-the-shelf reuse of code packaged as components. Containers provide services so that component developers can write high-level business logic instead of infrastructure such as networking code. Development automation is achieved through development environments that allow the application developer to assemble components, usually using a visual metaphor.
The enterprise component model
Enterprise component models such as EJB and ActiveX/MTS bring the component model of
development to middleware. Enterprise middleware development is notoriously complicated --
it involves not only business logic, but concurrency and scaling issues, as well as gluing
together incompatible systems on incompatible platforms.
Enterprise component models solve middleware development complexity by factoring all of this infrastructure into containers and servers. This allows the middleware developer to focus on writing the business logic, without having to worry about synchronization, scalability, transaction integrity, networking, distributed object frameworks, and other related matters.
In other words, the enterprise component model offers developers the following advantages:
EJB: An overview
An EJB runtime environment is composed of a server and a set of containers. The server is
not an application server; instead, it routes method calls to the enterprise beans
deployed under its containers and provides services to these containers and their
components.
The services provided are defined by contracts between the various parts of the EJB architecture, such as the contract that exists between the container and the beans in it. These contracts provide interfaces that decouple parts of the architecture into roles.
EJB roles
The EJB specification defines a number of roles necessary in implementing the EJB
component architecture. The roles are logical in nature, so multiple roles may in fact be
performed by the same party. Here's a brief look at the roles EJB defines:
The interface between server and container is vendor-specific in EJB 1.0. A server vendor usually provides containers for use with its EJB server.
The diagram below illustrates EJB roles and deployment.
|
Session beans vs. entity beans
There are two types of enterprise Java beans: session and entity.
A session enterprise bean models a connection, or session, with a single
client. Session beans persist only for the life of the connection with the client. If the
EJB server crashes, the session bean dies. A bean must implement the interface javax.ejb.SessionBean
to be a session bean.
When a new client references a session bean from the server, the container creates a new instance of the session bean, which is tied to the client that made the reference request through a bean object provided by the container. The session bean may then act on data in a database in some way, including taking part in transactions.
Entity beans model business objects that need to persist beyond the life of a
client instance. Each instance of an entity bean can be accessed by multiple clients
simultaneously. Entity beans survive crashes of the server. A bean must implement the
interface javax.ejb.EntityBean
to be an entity bean.
The Enterprise bean provider
When we convert the Forum backend into a bean, we will be acting in the role of bean
provider.
The EJB provider has to adhere to two contracts: the client contract and the component contract. The client contract is the view that the client sees of the bean. The component contract is the relationship between the bean and the container.
The following are produced by the bean provider to implement the provider's responsibilities with respect to these contracts:
Porting the Forum server to EJB
In our last encounter with the discussion forum application, we implemented its server as
an RMI server.
This month, we're going to implement the server side as a session EJB. The first step in this process is to set up the EJB development environment.
Setting up the EJB development environment
Setting up the EJB development environment is fairly straightforward:
The files unpack as javax/ejb
and so can be put directly into the project
directory. You can also add them to the classpath if you prefer.
Create a directory called jndi
in the project directory and put lib/
and examples/
from the JNDI zip file into it.
The JNDI classes are
contained in lib/jndi.jar
.
Now that the development environment is set up, it's time to do convert the Forum. The
diagram depicts what the ForumSessionServer
bean will contain in its ejb-jar
file.
|
Writing the remote interface
ForumSessionServer
(the EJB remote interface) defines all the business methods of the bean, as shown in the
figure below.
The following are the requirements for the remote interface:
java.ejb.EJBObject
. throws
clause must include java.rmi.RemoteException
.
import java.util.*;
import java.rmi.*;
interface ForumSessionServer extends javax.ejb.EJBObject {
// from Forum 1.0 API interface
Hashtable loadAllThreads () throws RemoteException;
Vector loadThreadArticles (String t) throws RemoteException;
boolean postArticle (String art, String t) throws RemoteException;
}
Writing the home interface
ForumSessionServerHome
(the EJB home interface) provides the client with methods to create an instance of the
bean and retrieve a remote reference to it. These methods are all called create.
The requirements for this interface are as follows:
javax.ejb.EJBHome
. create(...)
method, which must
be called create. The return type for the create(...)
methods must
be the remote interface. java.rmi.RemoteException
and javax.ejb.CreateException
. create(...)
methods return the remote interface type, while the bean class returns void
. import java.rmi.*;
import javax.ejb.*;
interface ForumSessionServerHome extends EJBHome {
public ForumSessionServer create (String d, String db, String u, String p,
String t) throws RemoteException, CreateException;
}
Writing the ForumSessionServerBean
class
The EJB bean class, ForumSessionServerBean
,
provides the implementation for the business methods that the client can call. It uses the
services provided by the container to handle requests from the client. The container also
provides a SessionContext
object and notifications of certain events.
The requirements for the bean implementation class are:
SessionBean
interface. create(...)
methods. The methods should have the modifiers public void
and be named according to the naming convention ejbCreate(...)
The bean class can also implement the javax.ejb.SessionSynchronization
interface, which provides notifications regarding the state of a transaction containing a
business method.
import java.util.*;
import java.sql.*;
import javax.ejb.*;
public class ForumSessionServerBean implements SessionBean {
SessionContext sessionContext;
String driver, dbURL, user, passwd, tableName;
// SessionBean methods
public void setSessionContext (SessionContext sc) {
// called first by container after Class.newInstance ()
this.sessionContext = sc;
}
public void ejbRemove () {
// called before container removes bean instance
}
public void ejbActivate () {
// called after bean is activated to allow resource setup
}
public void ejbPassivate () {
// called before bean is passivated to allow resource cleanup
}
Here we see the SessionBean
methods that are required of all session
beans. The setSessionContext()
method is called by the container immediately
after the new bean instance is created. The SessionContext
is passed into the
bean instance with this call.
The ejbRemove()
method is called by the client when it is through with a
bean. If the client never calls this method for some reason, the container has the option
of removing the EJB instance itself after some timeout period.
The ejbActivate()
and ejbPassivate()
methods are used by the
container to notify the bean that it is about to be taken out of or put into secondary
storage, respectively.
// ForumSessionServerHome method
public void ejbCreate (String d, String db, String u, String p, String t) {
// called second by container
this.driver = d;
this.dbURL = u;
this.passwd = p;
this.tableName = t;
}
// ForumSessionServer business methods
Hashtable loadAllThreads () {
// open db connection
// load threads from db
// close db connection
// return a Hashtable with the threads and empty Vectors
}
Vector loadThreadArticles (String t) {
// open db connection
// load articles from thread t from db
// close db connection
// return a Vector with all the articles from thread t
}
boolean postArticle (String art, String t) {
// open db connection
// post article on thread t to the database
// close db connection
return true;
}
}
The method of ForumSessionServerHome
is the single create (...)
method. This method can be overloaded to accept any number of arguments. These arguments
are used to pass initial "conversational state" into the client's bean object.
The business methods should be filled in with database-specific code. Note that a session EJB does not keep permanent state information as an entity EJB does. The session bean is visible only to the client that creates it and is (eventually) removed when its client goes away.
Now that the bean code is defined, it should be compiled into class files for deployment packaging.
The deployment descriptor
The deployment descriptor provides details on EJB deployment to the runtime container. The
descriptor is a serialized instance of javax.ejb.deployment.SessionDescriptor
.
EJB provider tools typically handle the task of creating the serialized deployment
descriptor. However, you can do it manually by writing a mini-application that creates an
instance of the deployment descriptor and serializes it to the filesystem.
The deployment descriptor instance has its session timeout set to a timeout value, or
0, to indicate that the container should use a container default timeout. It also has its StateManagementType
set to STATEFUL_SESSION
or STATELESS_SESSION
, depending on
whether or not the bean keeps state in instance variables.
For the ForumSessionServer
bean, we call the following methods on our
deployment descriptor instance:
deploymentDescriptor.setSessionTimeout (0);
deploymentDescriptor.setStateManagementType (SessionDescriptor.STATELESS_SESSION);
Once these values are set, the deployment descriptor instance should be serialized to a
file. The serialized deployement descriptor for the ForumSessionServer
should
be called ForumSessionServerDeployment.ser
.
Packaging the ForumSessionServer EJB
The final step for the bean provider is to package the ForumSessionServer
EJB
into an ejb-jar file for deployment.
The ejb-jar file contains a manifest file that identifies the EJBs included in the
file. The manifest file must be named META-INF/MANIFEST.MF. The format of the manifest
file for the ForumSessionServer is the following, with the Name:
field set to
the name of the deployment descriptor:
Name: ForumSessionServerDeployment.ser
Enterprise-Bean: True
The two interface files and the bean class file go into the ejb-jar, along with the
deployment descriptor and a serialized Properties
object, if one is needed.
The Properties
object has key/value pairs that represent any environment
properties that the bean will need when it is instantiated by the container. Our ForumSessionServerBean
doesn't require a Properties
object.
All that's left is to create the ejb-jar file (use the jar
utility) and
the bean is completely packaged and ready to be deployed.
Deployment to the EJB container
The person acting as EJB deployer will deploy the ejb-jar file to the EJB server node. The
EJB container tools, provided by the container vendor, will generate the support classes
necessary to do this.
Using the ForumSessionServer
in the Forum client
Recall that each client instance of the Forum consists of two primary objects -- a Forum
,
which is a Frame
, and an associated communications object. The Forum
contains the GUI and handles user events, and the ForumComm
implements the
actual networking tasks involved with talking to the server.
The Forum client essentially needs only to replace its RMI lookup code with JNDI code
to find the ForumSessionServer
:
// props is a Properties that contains the server location and type of context
Context context = new InitialContext (props);
ForumSessionServerHome fssh;
fssh = (ForumSessionServerHome) context.lookup("apps/ForumSessionServer");
ForumSessionServer server;
server = fssh.create ("driver", "location", "pass",
"tablename");
The new code goes in ForumComm
in place of the RMI code that is already
there.
When the client is ready to shut down, it should remove the ForumSessionServer
bean object from the server:
server.remove ();
Conclusion
As you can see, writing a session bean is pretty easy. Thanks to the support that the
container and server provide, you are not responsible for writing networking,
synchronization, transaction management, or any other infrastructure to support the bean's
business logic. The work to produce the original RMI implementation was far more tedious!
In addition, you can deploy the ForumSessionServer
EJB on any node running an
EJB server. You can also provide it to a third party for use as a building block in an
application.
You can apply the techniques used in creating the Forum EJB to projects of your own if the backend has session-like characteristics. You can also use entity EJBs, which are a bit more complicated, to model objects that represent permanent entities. In either case, writing to EJB confers numerous advantages over more "old fashioned" ways of writing applications.
About the author
The software industry is a strange world, where the only real sanctuary is to be quick or be dead. Fear of the dark can make you rue the evil that men do and all the wasted years. Sometimes it seems that the iron maiden would be kinder. But Michael, like thousands of his fellow developers, tries his best every day to be a trooper and fly where eagles dare.
Information about EJB
EJB development libraries and documentation
Previous Step by Step articles
(c) Copyright 1998 Web Publishing Inc., an IDG Communications company
Feedback: jweditors@javaworld.com
Technical difficulties: webmaster@javaworld.com
URL: http://www.javaworld.com/jw-07-1998/jw-07-step_p.html
Last modified: Thursday, July 01, 1999