Write a session EJB

Find out how EJB frees developers from the complexity of middleware development by providing complete infrastructure support

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:

  • Components contain only business logic
  • Pluggable, reusable components
  • Scalability
  • Resource management
  • Transactions support
  • Concurrency management

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:

Server provider

The server provider provides the EJB server, which handles distributed object, distributed transactions management, and other services for enterprise beans in containers. Examples of server providers are OS, database, and middleware vendors.

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.

Container provider

The container provider produces a container, which is the context that interfaces with enterprise beans at runtime. The container can implement the session bean contract or the entity bean contract. We'll discuss these contracts later on.

The container provider also makes tools available for the deployer to use in deploying enterprise beans in the runtime environment. In many cases the server provider also acts as the container provider.

Enterprise bean provider

The Enterprise bean provider writes enterprise beans to make up specific applications. The provider must produce several necessary items (see The Enterprise bean provider) and bundle them into an ejb-jar, which is the file packaging structure for an enterprise bean. The packaged bean then goes to the deployer and/or application assembler.

Deployer

The deployer takes beans produced by the enterprise bean provider and deploys them in the backend runtime environment. This process may involve mapping the security roles set by the beans to the security roles required by the organization.

The deployer may also customize the functionality of an enterprise bean by writing a wrapper for its business methods using container tools.

Application assembler

The application assembler uses the client view contract of the enterprise beans deployed at the backend to assemble client applications. The application assembler may also produce new beans by combining existing beans.

The diagram below illustrates EJB roles and deployment.

The flow starts with the EJB provider, which creates the bean and makes it available to application assemblers and EJB deployers. A deployer installs the bean onto a runtime node, which already has an EJB server and container(s) provided by the server and container provider, respectively.

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:

  • EJB remote interface class file
  • EJB home interface class file
  • EJB class file

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:

  1. Download the EJB and JNDI classes (see Resources )

  2. Set up the EJB classes

    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.

  3. Set up the JNDI files

    Create a directory called jndi in the project directory and put lib/ and examples/ from the JNDI zip file into it.

  4. Set up your CLASSPATH to see the JNDI classes

    The JNDI classes are contained in lib/jndi.jar.

  5. Set up the documentation (optional)

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.

An EJB contains two interface files and one class file in its ejb-jar file. The ForumSessionServerHome interface extends the javax.ejb.EJBHome interface, the ForumSessionServer extends the javax.ejb.EJBObject interface, and the ForumSessionServerBean implements the javax.ejb.SesionBean interface.

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:

  • The remote interface must extend java.ejb.EJBObject.

  • The methods must be valid RMI methods. Their return values and arguments must be serializable types and the throws clause must include java.rmi.RemoteException.

  • Each method in the remote interface must have a matching method signature and implementation in the EJB class. The implementations in the EJB class must throw the same business logic exceptions that the remote interface does.

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:

  • The home interface must extend javax.ejb.EJBHome.

  • The home interface must define at least one create(...) method, which must be called create. The return type for the create(...) methods must be the remote interface.

  • The methods must be valid RMI methods and must throw java.rmi.RemoteException and javax.ejb.CreateException.

  • The home interface methods must match the counterpart methods defined in the EJB class (named ejbCreate). The only difference is the return type -- the home interface 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:

  • The EJB bean class must implement the SessionBean interface.

  • The EJB bean class cannot be abstract.

  • The EJB bean class must have methods and implementations that match the home interface's create(...) methods. The methods should have the modifiers public void and be named according to the naming convention ejbCreate(...)

  • The EJB bean class methods must match the remote interface's business methods. These method names must not collide with methods defined by the EJB component model.

  • The methods must all be legal RMI methods.

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.

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 Shoffner, like thousands of his fellow developers, tries his best every day to be a trooper and fly where eagles dare.

Learn more about this topic

  • Download the complete source as a zip file http://www.javaworld.com/jw-07-1998/step/jw-07-step.zip
  • Download the complete source as a gzipped tar file http://www.javaworld.com/jw-07-1998/step/jw-07-step.tar.gz
  • Information about EJB
  • EJB development libraries and documentation
  • Previous Step by Step articles

Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more