Empower your EJB clients with mobile actions
- By Roger L. Cauvin
- June 24, 2001
NOTE: All code listings from this article are available in the
Java Report Online Previous Issues Code section.
Enterprise JavaBean (EJB) Technology enables client programs to access services and database entities remotely. The performance and scalability of applications that use your enterprise beans can suffer if client programs pass large objects to your enterprise beans, or make many remote method calls on them. To remedy these performance and scalability problems, you can include methods in your enterprise beans' interface that allow client programs to define mobile actions and perform them on your enterprise beans.
Consider a client program that iterates through a large collection of server objects, searching for a particular item of interest. Depending on the remote interface the EJB provides, the client can accomplish this task in different ways. In this example, a client interacts with an employee storage service to search for an employee with a particular name. Each employee has a name, social security number, and marital status:
// Employee interface visible to session bean and client.
public interface Employee
{String getName();
String getSSN();
boolean isMarried();
String getSpouseName();}
Approaches To Use
There are four approaches a client program can use to iterate through a large collection of server objects (see Listing 1).
Approach 1. A session bean in its remote interface exposes a method for obtaining the entire collection of objects. The client program invokes this method to retrieve the collection and subsequently iterate through its items.
EmployeeStorage employeeStorage = employeeStorageHome.
create();
Vector employees = employeeStorage.retrieveEmployees();
Enumeration enumeration = employees.elements();
boolean wasFound = false;
Employee employee = null;
while (!wasFound && enumeration.hasMoreElements())
{employee = (Employee) enumeration.nextElement();
wasFound = employee.getName().equals("Jane Doe");}
if (wasFound)
System.out.println("Found employee " + employee + ".");
This approach results in a large collection of items traveling over the network, even though the client program is interested in only one item. Serializing large objects across the network reduces the scalability and performance of enterprise applications.
Approach 2. The client program can find the object by repeatedly querying the collection of server objects (see Listing 2).
Using this approach, the client program retrieves a list of social security numbers, and queries the session bean for each corresponding employee until it finds the desired one. The client program avoids serializing the entire collection of relatively heavyweight employee objects across the network, but suffers a different performance penalty. A call to an enterprise bean requires a round-trip across the network. As the code and number of clients scale, they make many of these calls. The overhead of these calls significantly degrades performance, likely to the point that it is much more expensive to use this approach than it is to retrieve the entire list of objects.
Approach 3. To avoid both the serializing of large objects and repeated trips across the network, have the session bean's remote interface provide a specialized method. In this scenario, the EmployeeStorage session bean provides an overloaded retrieveEmployeeByName method. (Assume for simplicity's sake that no two employees have the same name.)
EmployeeStorage employeeStorage = employeeStorageHome.
create();
Employee employee = employeeStorage.retrieveEmployee
ByName("Jane Doe");
if (employee != null)
System.out.println("Found employee " + employee + ".");
Using a specialized method allows a client program to avoid serializing large objects and repeated trips across the network. Moreover, it is simpler for the client program. When you can anticipate the needs of the client program, this solution is ideal. However, you cannot always foresee what client programs will need to do with your enterprise beans. What if the client wishes to search for employees who are married to each other and remove them from the database? It is doubtful you could have anticipated this need and provided a
removeMarriedEmployees method in the session bean's remote interface.
Approach 4. Use mobile actions to provide an extensible, scalable, and fast means of performing arbitrary actions on enterprise beans. With the Mobile Action design pattern, you must:
- Define a local interface that contains all of the methods in the remote interface, except the methods do not throw RemoteException.
- Have the bean class implement the local interface.
- Define an interface that represents an action and exposes a single perform method. The method accepts an instance of the local interface.
- Provide a performAction method in the local and remote interfaces that enables a client program to perform any arbitrary action on the server side. The method accepts an instance of the action interface.
The client defines an action and performs it using the EJB. Applying Approach 4 to the employee storage example yields the following client code:
EmployeeStorage employeeStorage = employeeStorageHome.
create();
EmployeeStorageAction action = new FindByNameAction
("Jane Doe");
Employee employee = (Employee) employeeStorage.perform
Action(action);
if (employee != null)
System.out.println("Found employee" + employee + ".");
The client then defines the
FindByNameAction class (see Listing 3).
With this approach, the client program creates an instance of the FindByNameAction action and performs it on the enterprise bean by calling the bean's performAction method. This call serializes the action from the client to the server side. Note that the client program's action class must implement the java.io.Serializable interface to indicate that its instances are mobile.
The instance of the session bean class turns around and invokes the perform method on the action, passing a reference to itself as a parameter. The action's perform method then makes local method calls on the bean to retrieve the collection of employees and find the employee with the target name.
Approach 4 is desirable for the following reasons:
- It avoids serializing large objects over the network. The action retrieves the collection on the server side, so the collection does not travel across the network.
- It avoids repeated remote method invocations. The client program makes only one remote method invocation; all other interactions with the enterprise bean occur on the server side.
- It provides the EJB client with the ability to define and perform arbitrary actions on the enterprise bean, without requiring you to anticipate the specific needs of the client program.
- Client developers can implement actions that are not coupled to enterprise beans. It is possible to implement the same service a session bean provides, or implement the same domain object an entity bean represents, as an ordinary Java class. A client program can perform the same actions on local services and objects as it performs on remote services and entities.
Consequences of the Mobile Action Pattern
Before using the Mobile Action pattern in an application, consider its consequences. Because an action directly accesses functionality through a local interface, you cannot specify security or transaction settings that will affect the action. In addition to security and transaction management, any other services an EJB container provides will not apply when an action makes local calls on an enterprise bean. An action represents a transaction on an enterprise bean that an EJB container can manage only when the transaction begins and ends.
A "session bean" typically represents a remote service. Figure 1 shows the general structure of classes in the Mobile Action pattern as it applies to session beans. The diagram includes an interface representing a service, an interface representing an action on that service, home and remote interfaces for a session bean, and a session bean class that implements the service interface.
Figure 1. Session beans in Mobile Action pattern.
While a session bean represents a service, an entity bean typically represents remote data in a database. Figure 2 shows the Mobile Action pattern applied to entity beans. The structure of classes for this application of the pattern is the same as that for session beans. Instead of showing interfaces that represent a "service" and an "action upon that service," the diagram shows interfaces that represent "data" and an "action upon that data."
Figure 2. Entity beans in Mobile Action pattern.
The benefits of using the Mobile Action pattern for entity beans are the same as those for session beans, with an extra advantage. Depending on the contents of an entity bean's deployment descriptor, each client call on an entity bean that modifies its instance variables typically results in a database transaction. The Mobile Action pattern enables a client to package any number of entity bean modifications into a single action, and execute them on the server side before the enterprise bean or container commits them to the database.
The Mobile Action pattern resembles Command and Strategy patterns described in Design Patterns.1 It is possible to enhance the pattern by incorporating the Acyclic Visitor pattern.2
Conclusion
Developers can build scalable and fast enterprise applications using EJBs. Doing so, however, requires careful consideration of the overhead of remote method calls. The number of remote method calls, and the size of the objects that client programs pass in such calls, can significantly affect scalability and performance. Using the Mobile Action pattern enables clients to define arbitrary actions and have enterprise beans perform them on the server side, thereby reducing the number and size of remote method invocations.
References
- Gamma, E. et al. Design Patterns: Elements of Reusable Object-Oriented Software, Addison–Wesley, 1995.
- Martin, Robert C. "Acyclic Visitor," http://www.objectmentor.com.
EJBs force testing changes
Listing 1
Listing 1