EJB fundamentals and session beans

Begin exploring the world of EJBs

1 2 3 4 Page 3
Page 3 of 4

Consider a fictitious stock trading application where the client uses the buy() and getTotalPrice() methods of a StockTrader session bean. If the user has several different stocks to buy and wants to see the running total price on the tentative purchases, then that state needs to be stored somewhere. One place to store that kind of transient information is in the instance variables of the session bean itself. This requires that the session bean be defined as stateful by usage of the @Stateful bean class metadata descriptor.

There are advantages and disadvantages to making a session bean stateful. The following are some of the advantages:

  • 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.

Figure 6. A simple calculator that uses a stateful session bean

There are three Java source files in this example: Calculator.java (in the beans package), CalculatorBean.java (in the beans package), and CalculatorClient.java (in the client package). Since CalculatorClient.java focuses primarily on presentation, we won't list it here.

Listing 4 shows the code for the bean interface, Calculator.java. It defines the business method of the calculator.

Listing 4. Calculator.java

 

package beans;

import javax.ejb.Remote;

@Remote public interface Calculator { public void clearIt(); public void calculate(String operation, int value); public int getValue(); }

Listing 5 shows the code for the bean class, CalculatorBean.java.

Listing 5. CalculatorBean.java

 

package beans;

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; } }

Add these code files to a new application directory called SimpleCalculatorApp. Within the directory add beans and client subdirectories. Place Calculator.java and CalculatorBean.java in the beans directory, and CalculatorClient.java in the client directory.

Now compile the .java files following the same instructions as in the previous example. At the command line, type the following (again, remember that this is all on one line):

 > set CLASSPATH=.;C:\jboss\lib\concurrent.jar;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.deployerjboss-aspect-library.jar 

Next, within the SimpleCalculatorApp directory where the client and beans directories are located, execute the following commands from the command prompt:

 > javac -d . client/*.java
> javac -d . beans/*.java

Now enter the following command at the prompt:

 >jar cf SimpleCalculatorApp.ejb3 SimpleCalculatorApp

Then copy the resulting EJB3 file to your JBoss deployment directory:

 %JBOSS_HOME%\server\all\deploy.

Running the stateful session bean application

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:

 > set CLASSPATH=.;C:\jboss\lib\concurrent.jar;
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.deployerjboss-aop.jar;
C:\jboss\server\all\deploy\jboss-aop.deployerjboss-aspect-library.jar 

Next, with SimpleCalculatorApp as the current directory, execute the following command from the operating system prompt:

 > java 
-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

The GUI of the client should appear, as shown earlier in Figure 6.

To operate the calculator, type a number into the text box, select an operation (+ or -) from the drop-down list, and click the = button. The running total will be displayed beside the Calculator value label.

Reviewing the stateful session bean source code

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.

The client is a standard Java Swing application, complete with GUI components and event-handler methods. The client needs to call methods of the stateful session bean, so as in the previous example, it gets a reference to the bean's remote interface and gets a reference to the session bean on the server. The code that performs this is in the getCalculator() method of the CalculatorClient class, which is called from the constructor:

 

private Calculator getCalculator() { 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; }

When the = button is clicked, two things are passed to the calculate() method of the calculator session bean: the operator (either + or -) and the value to be added or subtracted from the running total:

 _calculator.calculate(oper, operVal);

Since it is a stateful session bean, it is able to store the running total in an instance variable. The client then calls the getValue() method of the calculator session bean to retrieve the running total and subsequently display it:

 _topNumber.setText("" + _calculator.getValue());

When the user clicks the Clear button, the clearIt() method of the calculator session bean is called, which sets the running total to 0.

The implementations of the three calculator business methods of the CalculatorBean class follow. They manipulate the instance variable named _value, which holds the running total between invocations of any of these calculator session bean methods.

 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;
}

The bean indicates its use by the presence of the @Stateful metadata descriptor, just as our earlier bean indicated it was stateless by the use of the @Stateless descriptor. This pattern will follow throughout much of Java EE 5. Much of the hard work present in earlier versions of Java EE has been abstracted into the implementation behind the metadata descriptors.

Keep in mind that a session bean that holds values in instance variables should never be configured as stateless, because the values of the instance variables are not predictable. This is because the EJB container has complete control over managing stateless (and stateful) session beans, including initializing the values of instance variables as the bean is shared among various clients. This is a common trap because sometimes the values are retained, giving a false indication that everything is okay, and then one day, you can't figure out why the program isn't working correctly. From personal experience, that's a fun one to diagnose!

Summary

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.
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
1 2 3 4 Page 3
Page 3 of 4