EJB fundamentals and session beans
By Jim Crume, Kevin Mukhar, James L. Weaver, Chris Zelenak
Java Enterprise Edition (Java EE) has a powerful facility dedicated to expressing the business logic of an application and for accessing a database using a JavaBeans-like concept. That facility is Enterprise JavaBeans, known as EJBs for short.
In this article, we'll begin exploring the world of EJBs, which is a very important capability of the Java EE platform. EJBs provide infrastructure for developing and deploying mission-critical, enterprise applications. We'll first look at some EJB fundamentals, and then focus on one type of EJB: the session bean.
In this article, you will learn the following:
-
The benefits of using EJBs
-
The three kinds of EJBs: session, entity, and message-driven beans
-
The makeup of session beans
-
How to develop session beans
-
Differences between stateful and stateless session beans
Understanding EJBs
Application architectures often consist of several tiers that each has its own responsibilities. One such architecture that consists of three tiers is illustrated in the Unified Modeling Language (UML) diagram shown in Figure 1.
|
Note |
---|
JavaBeans and Enterprise JavaBeans are two different things, but because of their similarities (and for marketing reasons), they share a common name. JavaBeans are components built in Java that can be used on any tier in an application. They are often thought of in relationship to servlets and as GUI components. Enterprise JavaBeans are special, server-based components, used for building the business logic and data access functionality of an application. |
Not too long ago, when system developers wanted to create an enterprise application, they would often start by "rolling their own" (or purchasing a proprietary) application server to support the functionality of the application logic layer. Some of the features of an application server include the following:
- Client communication: The client, which is often a user interface, must be able to call the methods of objects on the application server via agreed-upon protocols.
- Session state management: You'll recall our discussions on this topic in the context of JSP (JavaServer Pages) and servlet development back in Chapter 6.
- Transaction management: Some operations, for example, when updating data, must occur as a unit of work. If one update fails, they all should fail.
- Database connection management: An application server must connect to a database, often using pools of database connections for optimizing resources.
- User authentication and role-based authorization: Users of an application must often log in for security purposes. The functionality of an application to which a user is allowed access is often based on the role associated with a user ID.
- Asynchronous messaging: Applications often need to communicate with other systems in an asynchronous manner; that is, without waiting for the other system to respond. This requires an underlying messaging system that provides guaranteed delivery of these asynchronous messages.
- Application server administration: Application servers must be administered. For example, they need to be monitored and tuned.
The EJB specification
The EJB specification defines a common architecture, which has prompted several vendors to build application servers that comply with this specification. Now developers can get off-the-shelf application servers that comply with a common standard, benefiting from the competition (in areas such as price, features, and performance) among those vendors.
Some of the more common commercial EJB application servers are WebLogic (BEA), Java Enterprise System (Sun), OC4J containers for Oracle Database 10g, and WebSphere (IBM). There are also some very good open source entries in this market such as JBoss and JOnAS. Sun also provides an open source reference implementation (Java EE SDK) of the Java EE 5 and EJB 3.0 specifications that developers can use to develop and test applications for compliance with those specifications. (The reference implementation may not, however, be used to deploy production systems.) Currently under development, the reference implementation is codenamed "Glassfish." The platform provides a basic EJB 3.0 test platform; more details can be found on the Website and in the related discussion forums. These application servers, in conjunction with the capabilities defined in the EJB specification, support all of the features listed here and many more.
The EJB specification was created by experienced members of the development community; such a body is called an expert group. In the EJB specification's expert group are members from such organizations as JBoss, Oracle, and Google. Thanks to them, we now have a standard, specifications-based way to develop and deploy enterprise-class systems. We are approaching the Java dream of developing an application that can run on any vendor platform as-is. This is in contrast to the vendor-specific way we used to develop, where each server had its own way of doing things, and where the developer was locked into the chosen platform once the first line of code was written!
The version of the EJB specification that is included with the Java EE 5.0 recommendation is 3.0, and this is the version we refer to when discussing EJBs. The EJB 3.0 specification has added many improvements to its predecessor (version 2.1, which was a part of the J2EE 1.4 recommendation), including metadata annotations to simplify deployment concerns, a higher degree of control over bean persistence, and a much more simplified (but no less powerful) programming model for developing EJBs.
The three kinds of EJBs
There are actually three kinds of EJBs: session beans, entity beans, and message-driven beans. Here, we will present a brief introduction to each type of bean. The balance of this article will then focus on session beans.
Note |
---|
When referring to EJBs in the general sense, we'll use the term EJBs, enterprise beans, or simply beans. |
Session beans
One way to think about the application logic layer (middle tier) in the sample architecture shown in Figure 1 is as a set of objects that, together, implement the business logic of an application. Session beans are the construct in EJBs designed for this purpose. As shown in Figure 2, there may be multiple session beans in an application. Each handles a subset of the application's business logic.
A session bean tends to be responsible for a group of related functionality. For example, an application for an educational institution might have a session bean whose methods contain logic for handling student records. Another session bean might contain logic that maintains the lists of courses and programs available at that institution.
There are two types of session beans, which are defined by their use in a client interaction:
-
Stateless: These beans do not declare any instance (class-level) variables, so that the methods contained within can act only on any local parameters. There is no way to maintain state across method calls.
-
Stateful: These beans can hold client state across method invocations. This is possible with the use of instance variables declared in the class definition. The client will then set the values for these variables and use these values in other method calls.
There may be more work involved for the server to share stateful session beans than is required to share stateless beans. Storing the state of an EJB is a very resource-intensive process, so an application that uses stateful beans may not be easily scalable. Stateless session beans provide excellent scalability, because the EJB container does not need to keep track of their state across method calls. You'll see how to develop both stateless and stateful session beans later in this article.
All EJBs, session beans included, operate within the context of an EJB server, as shown in Figure 2. An EJB server contains constructs known as EJB containers, which are responsible for providing an operating environment for managing and providing services to the EJBs that are running within it.
In a typical scenario, the user interface (UI) of an application calls the methods of the session beans as it requires the functionality that they provide. Session beans can call other session beans and entity beans. Figure 2 illustrates typical interactions between the user interface, session beans, entity beans, and the database.
|
Entity beans
Before object orientation became popular, programs were usually written in procedural languages and often employed relational databases to hold the data. Because of the strengths and maturity of relational database technology, it is now often advantageous to develop object-oriented applications that use relational databases. The problem with this approach is that there is an inherent difference between object-oriented and relational database technologies, making it less than natural for them to coexist in one application. The use of entity beans is one way to get the best of both of these worlds, for the following reasons:
-
Entity beans are objects, and they can be designed using object-oriented principles and used in applications as objects.
-
The data in these entity bean objects are persisted in some data store, usually relational databases. All of the benefits of relational technologies—including maturity of products, speed, reliability, ability to recover, and ease of querying—can be leveraged.
In a typical EJB scenario, when a session bean needs to access data, it calls the methods of an entity bean. Entity beans represent the persistent data in an EJB application. For example, an application for an educational institution might have an entity bean named Student that has one instance for every student that is enrolled in an institution. Entity beans, often backed by a relational database, read and write to tables in the database. Because of this, they provide an object-oriented abstraction to some information store.
As shown in Figure 2, it is a good practice to call only session beans directly from the client, and to let the session beans call the entity beans. Here are some reasons for this:
-
This practice doesn't circumvent the business logic contained in the session beans. Calling entity beans directly tends to push the business logic into the UI logic, which is usually a bad thing.
-
The UI doesn't need to be as dependent on changes to the entity beans. The UI is shielded from these changes by the session beans.
-
In order for a client to interact with a bean on the EJB server, there must be a remote reference to the bean, which takes resources. There tends to be far more (orders of magnitude) entity bean instances in an application than session bean instances. Restricting client access to session beans conserves server and network resources considerably.
Note |
---|
Developing entity beans does not require a business interface; in fact, message-driven beans are the only EJBs that must implement some business interface. |
Message-driven beans
When an EJB-based application needs to receive asynchronous messages from other systems, it can leverage the power and convenience of message-driven beans. Asynchronous messages between systems can be analogous to the events that are fired from a UI component to an event handler in the same JVM. For example, in the business-to-business (B2B) domain, a wholesaler could have an EJB application that uses message-driven beans to listen for purchase orders issued electronically from retailers.
Which type of EJB should you use?
So, how do you decide whether a given EJB should be a session bean, entity bean, or a message-driven bean? Here are some guidelines for deciding:
-
Session beans are great at implementing business logic, processes, and workflow. For example, a StockTrader bean with buy() and sell() methods, among others, would be a good fit for a session bean.
-
Entity beans are the persistent data objects in an EJB application. In a stock trading application, a Stock bean with setPrice() and getPrice()methods would be an appropriate use of an entity bean. The buy() method of the previously mentioned StockTrader session bean would interact with instances of the Stock entity bean by calling their getPrice() methods, for example.
-
Message-driven beans are used for the special purpose of receiving asynchronous messages from other systems, like a wholesaler application that listens for purchase orders.
Now that we've covered some basics concerning the three types of EJBs, we'll use the rest of this article to take a closer look at the first type mentioned: session beans.
The anatomy of a session bean
Every session bean requires the presence of a bean interface and a bean class. A bean interface is the mechanism by which client code will interact with the bean internals, while the bean class is the implementation of those internals, as illustrated in Figure 3.
|
The implementation of the business logic of a session bean is located in its bean class. The bean class of the session bean must either implement the javax.ejb.SessionBean interface or prefix its class definition with the metadata descriptor @Stateless.
Note |
---|
Metadata is a new addition to the Java language with the introduction of J2SE 5.0. It effectively allows developers to elaborate on class definitions, adding further descriptive and behavioral information to the generation of the class file. The EJB 3.0 specification has used this facility to describe the majority of its workings. To learn more about this new addition to the Java language, read the official specification. |
The bean interface (or business interface, as some refer to it) that exposes the internals of the EJB to calling code may be implemented by the developer, or it can be generated automatically. The compiler will create a bean interface for you that is a map of the public methods available in the bean class.
As a naming convention, we'll append the word Bean to the name of a bean to indicate that it is a bean class. For example, a session bean with the name StockTrader would have a bean class named StockTraderBean.
Developing session beans
It is now time to put all this theory into practice. In this section, we're going to develop our first session bean in an example that's on par with the traditional "Hello World!" sample program.
First, we'll walk through the bean-creation code in a good bit of detail, reinforcing concepts we just covered and introducing new ones. Then we'll explain how to compile the example. For this, we'll use the Java compiler that comes with the Java 2 Platform, Standard Edition 5.0. Finally, we'll deploy the example in JBoss.
Using a stateless session bean
Since this is the first EJB example, we're going to walk through the code now and then run it later. There are three Java source files for this example: SimpleSession.java, SimpleSessionBean.java, and SimpleSessionClient.java.
Listing 1 shows the code for the remote business interface, SimpleSession.java.
Note |
---|
The term remote business interface signifies that this interface is accessed and called by "remote" clients. Don't jump to conclusions! We'll define what exactly is meant by that statement when we explain this code later on in the article. |
Listing 1. SimpleSession.java
package beans;
import javax.ejb.Remote;
@Remote
public interface SimpleSession
{
public String getEchoString(String clientString);
}
Listing 2 shows the code for the actual bean implementation, SimpleSessionBean.java.
Listing 2. SimpleSessionBean.java
package beans;
import javax.ejb.Stateless;
@Stateless
public class SimpleSessionBean implements SimpleSession {
public String getEchoString(String clientString) {
return clientString + " - from session bean";
}
}
Finally, Listing 3 shows the client code to test the session bean.
Listing 3. SimpleSessionClient.java
package client;
import beans.SimpleSession;
import javax.naming.InitialContext;
public class SimpleSessionClient {
public static void main(String[] args) throws Exception
{
InitialContext ctx = new InitialContext();
SimpleSession simpleSession
= (SimpleSession) ctx.lookup(SimpleSession.class.getName());
for (int i = 0; i < args.length; i++) {
String returnedString = simpleSession.getEchoString(args[i]);
System.out.println("sent string: " + args[i] +", received string: " + returnedString);
}
}
}
Organize the files in a directory called SimpleSessionApp, as shown in Figure 4.
|
After you've created and organized the sample session bean files as just described, follow these steps to compile the application:
- Open a command prompt in the SimpleSessionApp directory.
- Compile the classes, ensuring that the CLASSPATH is set to contain all the necessary JBoss libraries. These libraries contain all of the EJB functionality needed to make your code interact with the application server, so it is extremely important that you get this step right. At the command line, type the following (this should all be on one line):
> set CLASSPATH=.;C:\jboss\lib\concurrent.jar;
C:\jboss\lib\jboss-common.jar;
c:\jboss\client\jboss-j2ee.jar;
c:\jboss\lib\commons-httpclient.jar;
C:\jboss\server\all\lib\jboss.jar;
C:\jboss\server\all\lib\jboss-remoting.jar;
C:\jboss\server\all\lib\jboss-transaction.jar;
C:\jboss\server\all\lib\jnpserver.jar;
C:\jboss\server\all\deploy\ejb3.deployer\jboss-ejb3.jar;
C:\jboss\server\all\deploy\ejb3.deployer\jboss-ejb3x.jar;
C:\jboss\server\all\deploy\jboss-aop.deployer\
jboss-aop.jar;
C:\jboss\server\all\deploy\jboss-aop.deployer\
jboss-aspect-library.jar - Within the SimpleSessionApp directory where the client and beans directories are located, execute the following commands from the command prompt:
> javac -d . client/*.java
> javac -d . beans/*.javaThe –d option tells the Java compiler to place the class files in subdirectories matching their package structure, subordinate to the given directory. In this case, the given directory is the current directory, signified by the period. As a result, the Java class files should end up in the same directories as the source files.
Deploying the simple session bean application
Now we need to start the JBoss Server. Once the JBoss Server is up and running, you can deploy your class files. In order to deploy your class files, you need to package your different application components together in a compressed jar file. Make the extension of this file .ejb3, so that JBoss can deploy it. To create the application EJB3 file, open a command prompt in the same directory that SimpleSessionApp resides in and type in the following command:
>jar cf SimpleSessionApp.ejb3 beans\*.java
Now copy the resulting EJB3 file to the %JBOSS_HOME%/server/all/deploy directory. If your JBoss installation is in C:\JBoss, for example, copy the file to C:\JBoss\server\all\deploy.
JBoss will automatically detect and deploy your code for you. The directory structure should now have the files shown in Figure 5.
|
To run the sample client, set the CLASSPATH to the same value you did earlier to compile the application.
C:\jboss\lib\jboss-common.jar;
C:\jboss\server\all\lib\jboss.jar;
C:\jboss\server\all\lib\jboss-remoting.jar;
C:\jboss\server\all\lib\jboss-transaction.jar;
C:\jboss\server\all\lib\jnpserver.jar;
C:\jboss\server\all\deploy\ejb3.deployer\jboss-ejb3.jar;
C:\jboss\server\all\deploy\ejb3.deployer\jboss-ejb3x.jar;
C:\jboss\server\all\deploy\jboss-aop.deployer\jboss-aop.jar;
C:\jboss\server\all\deploy\jboss-aop.deployer\
jboss-aspect-library.jar
-Djava.naming.factory.initial=
org.jnp.interfaces.NamingContextFactory
-Djava.naming.factory.url.pkgs=
org.jboss.naming:org.jnp.interfaces
-Djava.naming.provider.url=
localhost client.SimpleSessionClient
Now is the time for all good men
sent string: is, received string: is
sent string: the, received string: the
sent string: time, received string: time
sent string: for, received string: for
sent string: all, received string: all
sent string: good, received string: good
sent string: men, received string: men
We have three Java source files to walk through here. We'll start with the client and work our way back up to the session bean interface and class.
SimpleSession simpleSession
= (SimpleSession) ctx.lookup(SimpleSession.class.getName());
String returnedString = simpleSession.getEchoString(args[i]);
System.out.println("sent string: " + args[i] +", received string: " + returnedString);
}
return clientString + " - from session bean";
}
@Remote
public interface SimpleSession
import javax.ejb.Stateless;
@Stateless
public class SimpleSessionBean implements SimpleSession
As mentioned previously, session beans are a great choice for implementing business logic, processes, and workflow. When you choose to use a session bean to implement that logic, you have yet another choice to make: whether to make that session bean stateful or stateless.
- Transient information, such as that described in the stock trading scenario, can be stored easily in the instance variables of the session bean, as opposed to defining and using entity beans (or JDBC) to store it in a database.
- Since this transient information is stored in the session bean, the client doesn't need to store it and potentially waste bandwidth by sending the session bean the same information repeatedly with each call to a session bean method. This bandwidth issue is a big deal when the client is installed on a user's machine that invokes the session bean methods over a phone modem, for example. Bandwidth is also an issue when the data is very large or needs to be sent many times repeatedly.
The main disadvantage is that stateful session beans don't scale up as well on an EJB server, because they require more system resources than stateless session beans do. Not only do stateful session beans require memory to store the state, but they also can be swapped in and out of memory (activated and deactivated) as the EJB container deems necessary to manage server resources. The state gets stored in a more permanent form whenever a session bean is deactivated, and that state is loaded back in when the bean is activated.
Note |
---|
The generic bean interface from which all EJBs derive defines several session bean lifecycle methods, including ejbActivate() and ejbRemove(). A stateful session bean class can implement these callback methods to cause special processing to occur when it is activated or removed. |
Using a stateful session bean
Let's look at an example of using a stateful session bean in a generally familiar context: the common calculator. This example mimics some very simple calculator operations: adding, subtracting, and keeping a running total. (This may not be very impressive by today's standards, but you would have paid good money for a calculator with those functions in the early 1970s!) That "keeping a running total" part is what demonstrates the use of a stateful session bean. Figure 6 shows the GUI client for this example.
|
import javax.ejb.Remote;
@Remote
public interface Calculator {
public void clearIt();
public void calculate(String operation, int value);
public int getValue();
}
import javax.ejb.Stateful;
@Stateful
public class CalculatorBean implements Calculator {
private int _value = 0;
public void clearIt() {
_value = 0;
}
public void calculate(String operation, int value) {
if (operation.equals("+")) {
_value = _value + value;
return;
}
if (operation.equals("-")) {
_value = _value - value;
return;
}
}
public int getValue() {
return _value;
}
}
C:\jboss\server\all\lib\jboss.jar;
C:\jboss\server\all\lib\jboss-remoting.jar;
C:\jboss\server\all\lib\jboss-transaction.jar;
C:\jboss\server\all\lib\jnpserver.jar;
C:\jboss\server\all\deploy\ejb3.deployer\jboss-ejb3.jar;
C:\jboss\server\all\deploy\ejb3.deployer\jboss-ejb3x.jar;
C:\jboss\server\all\deploy\jboss-aop.deployer\
jboss-aop.jar;
C:\jboss\server\all\deploy\jboss-aop.deployer\
jboss-aspect-library.jar
> javac -d . beans/*.java
After deploying the application, you can now run it. On a default Java EE 5 SDK/JBoss Windows installation, the CLASSPATH would be set correctly by using the following command:
C:\jboss\lib\jboss-common.jar;
C:\jboss\server\all\lib\jboss.jar;
C:\jboss\server\all\lib\jboss-remoting.jar;
C:\jboss\server\all\lib\jboss-transaction.jar;
C:\jboss\server\all\lib\jnpserver.jar;
C:\jboss\server\all\deploy\ejb3.deployer\jboss-ejb3.jar;
C:\jboss\server\all\deploy\ejb3.deployer\jboss-ejb3x.jar;
C:\jboss\server\all\deploy\jboss-aop.deployer\
jboss-aop.jar;
C:\jboss\server\all\deploy\jboss-aop.deployer\
jboss-aspect-library.jar
-Djava.naming.factory.initial=
org.jnp.interfaces.NamingContextFactory
-Djava.naming.factory.url.pkgs=
org.jboss.naming:org.jnp.interfaces
-Djava.naming.provider.url=
localhost client.CalculatorClient
To understand how this example works, we'll walk through some of the GUI client code contained in the CalculatorClient.java source file, and then we'll take a closer look at the EJB code.
Note |
---|
In the code examples, you'll notice that some of the import statements are wildcards and some explicitly name the class or interface. For instructional purposes, we've chosen to be explicit on the imports that are relevant to Java EE. We've chosen to be more frugal with lines of code by using wildcards for the more familiar ones that are relevant to J2SE. |
Calculator calculator = null;
try {
// Get a naming context
InitialContext ctx = new InitialContext();
// Get a Calculator
calculator
= (Calculator) ctx.lookup(Calculator.class.getName());
} catch(Exception e) {
e.printStackTrace();
}
return calculator;
}
public void clearIt() {
_value = 0;
}
public void calculate(String operation, int value) {
if (operation.equals("+")) {
_value = _value + value;
return;
}
if (operation.equals("-")) {
_value = _value - value;
return;
}
}
public int getValue() {
return _value;
}
In this article, we explained what EJBs are and built a case for using them. We touched on the three types of EJBs: session beans, entity beans, and message-driven beans. The balance of this article was then devoted to session beans, and we started that discussion by explaining that session beans are made up of two parts: the bean interface and the bean class. After finishing this article, you should know:
- What EJBs are, the different types of EJB, and their general behavior.
- How to create stateful and stateless session beans using the @Stateful and @Stateless metadata descriptors. You should also know how to invoke your session bean from a remote client by using a remote bean interface annotated by the @Remote descriptor. Making your application accessible to client applications is best facilitated by using session beans and will allow you to better focus your application's design by abstracting away the client concerns.
- The difference between stateful and stateless session beans. Stateful session beans are most suitable in situations where you must retain some information about the client's interaction with your application. Stateless session beans are best deployed when you need a very simple, low-overhead interface for your application's clients.
- How to deploy your EJB using the JBoss Server, and how to create a simple client application that will use the application server to invoke your EJB's functionality.
About the author
Jim Crume is a Java architect at Fusion Alliance, an Indianapolis, Indiana-based consulting company that specializes in Web application development. Crume has spent many years as a consultant and specializes in architecting and developing Web-based systems, but he particularly enjoys Java.
Kevin Mukhar is a software developer in Colorado Springs, Colorado. For the past seven years, he has worked on various software systems using different Java enterprise technologies. He has coauthored several other books, including Beginning Java Databases and The Ultimate Palm Robot. In addition to developing software during the day, he is working on a master’s degree in computer science.
James L. Weaver is the chief scientist at Learning Assistant Technologies, a company that specializes in developing learner-centric tools. He is also the president of JMentor, a Java mentoring, training, and consulting practice.
Chris Zelenak is a programmer at Learning Assistant Technologies, where he helps in the development of server-side Cocoon and Rails applications, Java and .Net client applications, and rampant devil’s advocacy. He recently graduated from the computer science department of Indiana Wesleyan University
-
"EJB Fundamentals and Session Beans" is an excerpt from Beginning Java EE 5: From Novice to Professional (Apress, October 2005; ISBN: 1590594703):
http://www.apress.com/book/bookDisplay.html?bID=420 -
Glassfish:
https://glassfish.dev.java.net/ -
For more information about the EJB specification:
http://java.sun.com/products/ejb/docs.html -
JSR 175: A Metadata Facility for the Java Programming Language:
http://jcp.org/en/jsr/detail?id=175
Resources