The Go-ForIt.com project is an e-business application developed by the DragonSlaying technical consulting team in the IBM Developer Relations organization. Go-ForIt is built on a logical three-tier architecture, a programming model advocated by J2EE, and uses the eXtreme Programming (XP) development methodology (see part 2 in the Go-ForIt series, eXtreme programming: deceptively simple innovation). Go-ForIt.com implements the model view controller (MVC) concept. In this article, we will discuss how to use the command framework in an n-tier architecture to reduce overhead and improve performance.
The components of the Go-ForIt.com application are:
- First tier
- The browser
- Second tier
- Servlets, JavaServer Pages (JSPs) technology, command beans and helper JavaBeans components
- Third tier
- Business logic, in Enterprise JavaBeans (EJB) technology, and a database
Sometimes it is necessary to issue requests to objects without knowing anything about the operation being requested or the receiver of the request. The command pattern, which is a well documented pattern, allows you to encapsulate the request as an object and the resulting request object can be stored or passed around.
A command is a Java class that:
- Corresponds to a specific business logic task
- Has a simple, uniform usage pattern
- Hides logic from the user interface (UI)
- Hides the specific connector interfaces
- Caches the information returned upon execution of the command
Generally, commands are implemented as JavaBeans components with the following methods. There must be a method defined for:
- Each input property xxx:
Void setXxx (Xxx xxx); - Each output property:
Xxx getXxx(); - Execution of the task:
public boolean execute();
There can be other methods: to do(), undo(), and reset() the command.
How does Go-ForIt.com use commands?
The Go-ForIt.com application uses commands to let the UI objects make requests to the back-end without knowing the what, how, and why of the controller objects or EJBs it needs to talk to. For this reason we developed commands for all possible user functions. We identified commands by having a concrete command class for every user level function. Our UI is in HTML/JSP form, which invokes a servlet, so we developed a concrete command for every function that the servlet calls.
Implementing the command pattern involved separation of tasks by role, such as UI developer and the Java business logic developer. Thus, the commands are used to communicate between the controller residing on the second tier and the model residing on the third tier in our MVC architecture. The servlet has no knowledge of what back-end objects it needs to communicate with to get a unit of work done; all it does is instantiate a command object and then set the input parameter of the command and call its execute method. When the command has finished performing the business logic, the result, if any, is stored in the command, so that the servlet can get the result values from the command object. The command pattern reduced the overhead of cross-tier communication in our application by caching the results.
The following diagram shows the interactions between the objects.
Figure 1. Sequence Diagram

The code in this section will help you understand how the command beans play a role in our application. The examples are part of the code that implements the User Registers user story (see Resources). The Registration.jsp collects all the personal information about the user, then calls the registration servlet. In the registration servlet we get all the data from the request object and store it in a client side Java bean called UserDataBean (see part 4 in the Go-ForIt series, "Bean" there, done that: Using client-side beans for component independence).
The next job of the registration servlet is to exercise the logic to register the user with the application. The process involves calling the UserController session bean and user entity bean, which perform some additional logic and then persist the user in the database. There's a lot of information the registration servlet has to know, if it were to do the whole task by itself. The developers who typically write the servlet are well versed with the application flow functions. Now, they need to know all the back-end details of how to call the appropriate EJB components to get the task done. We encapsulated all the back-end details in the UserRegisters command bean, so all the registration servlet has to do is call the execute method of the bean and the job gets done when the command returns.
Registration Servlet calls the UserRegistersCommandBean
public void performTask(
javax.servlet.http.HttpServletRequest req,
javax.servlet.http.HttpServletResponse res) {
UserDataBean user = new UserDataBean();
//instantiate the Command Bean
|
Our commands are designed to do one task only, which keeps our commands simple and easy to maintain. Our UserRegisters command bean has:
- A default constructor
- A setUser method that allows the calling object, in our case the servlet, to set the UserDataBean in the command
- An execute method that has the logic to perform the task
- A helper method getInitialContext(), which returns the initial context, and getUserControllerHome(), which encapsulates the EJB component look-up logic
UserRegisters Command Bean
package com.goforit.command;
import java.rmi.*;
import com.goforit.exception.*;
import javax.ejb.*;
import java.util.*;
import javax.naming.*;
import com.goforit.ejb.*;
import javax.rmi.*;
/**
* Command to register a new user
*/
public class UserRegistersCommandBean {
private InitialContext _initialContext = null;
private UserControllerHome _userControllerHome = null;
private String _userControllerJndiName = "com/goforit/ejb/UserController";
private com.goforit.user.UserDataBean _user;
/**
* UserRegistersCommandBean constructor comment.
*/
public UserRegistersCommandBean() {
super();
}
/**
* Performs task of persisting user in the database
* by calling EJBs at back end
* @param user com.goforit.user.User
* @exception com.goforit.exception.DuplicateUserException
* The exception description.
*/
public void execute()
throws com.goforit.exception.DuplicateUserException,
CreditCardNotAuthorizedException,
InvalidCreditCardNumberException, com.goforit.exception.CommandException{
try {
_userControllerHome = getUserControllerHome();
UserController userController = _userControllerHome.create();
userController.registerUser(_user);
} catch (java.rmi.RemoteException e) {
if ((e.toString().indexOf("DuplicateUserException")) > 1) {
throw new com.goforit.exception.DuplicateUserException();
}
if ((e.toString().indexOf("CreditCardNotAuthorizedException")) > 1) {
throw new com.goforit.exception.CreditCardNotAuthorizedException();
}
if ((e.toString().indexOf
("InvalidCreditCardNumberException")) > 1) {
throw new com.goforit.exception.InvalidCreditCardNumberException();
}
} catch (CreateException e) {
throw new com.goforit.exception.CommandException(e.toString());
}
}
/**
* Getter for the initialContext property.
* This method uses com.ibm.ejs.ns.jndi.CNInitialContextFactory to obtain an
* initial naming context.
* @return InitialContext The initial naming context.
*/
private InitialContext getInitialContext() throws NamingException {
if (this._initialContext == null) {
// Get the initial context
Properties p = new Properties();
// Use IBM name services
p.put(javax.naming.Context.PROVIDER_URL, "iiop://localhost:900/");
p.put(
javax.naming.Context.INITIAL_CONTEXT_FACTORY,
com.ibm.ejs.ns.CosNaming.NameServer.CONTEXT_FACTORY_CLASS);
try {
_initialContext = new InitialContext(p);
} catch (NamingException e) {
throw new NamingException(e.toString());
}
}
return this._initialContext;
}
/**
* Getter for the incrementHome property.
* This method uses the initial naming context to lookup
* the entry for the IncrementHome instance.
* @return The UserControllerHome instance.
*/
private UserControllerHome getUserControllerHome() {
if (this._userControllerHome == null) {
try {
InitialContext initContext = getInitialContext();
// The default JNDI name for Enterprise Java Beans created
// in VisualAge for Java is the fully-qualified name of the
// remote interface, with periods replaced by forward slashes.
String jndiName = UserController.class.getName().replace('.', '/');
Object o = initContext.lookup(jndiName);
this._userControllerHome = (UserControllerHome)
PortableRemoteObject.narrow(o, UserControllerHome.class);
} catch (NamingException e) {
.....
}
}
return this._userControllerHome;
}
/**
* Sets the user property (com.goforit.user.User) value.
* @param city The new value for the property.
* @see #getCity
*/
public void setUser(com.goforit.user.UserDataBean user) {
_user = user;
}
}
|
We implemented commands to execute locally in Go-ForIt.com, which means command objects execute in the same Java virtual machine (JVM) as the calling servlet. The command can also be implemented to execute remotely on another server, where the data resides. For more information, see the "Patterns Development Kit" listed in Resources.
Commands in e-business applications add value because they:
- Are implemented as serialized objects, can be streamed to any server supporting Java access to its resources, and can handle multiple protocols
- Allow data caching
- Make it easy to get access to the output data
- Make stable boundary business logic and UI logic
Command beans are Java beans that have a specific behavior. They help control and encapsulate the execution logic so you can control the bean selection and sequencing, queue them, and otherwise manipulate them. Commands help decouple the object that invokes the operation from the one that knows how to perform it. They help improve performance by creating a unit of work and executing it closer to the data on which the operation needs to be performed.
Watch for our next installment of the Go-ForIt chronicles, where we'll cover JUnit testing of EJBs in VisualAge for Java. To see the previous articles in our tale of dragonslaying, go to our overview.
- Follow the Go-ForIt series in this collection of existing articles.
- Become more familiar with IBM patterns for e-business.
- Download the Patterns Development Kit.
- Review the User stories (customer requirements) for the Go-ForIt application.
-
Design Patterns - Elements of Reusable Object-Oriented Software
by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (Addison Wesley)
-
Patterns in Java, Volume 1, A Catalog of Reusable Design Patterns Illustrated with UML
, by Mark Grand (Wiley)

Sandeep Desai is an e-business Architect in IBM's Developer Relations Technical Consulting in Austin, Texas. Sandeep works with IBM's Business partners, from startups to large firms, helping to evangelize, educate, and enable them on IBM's e-business platform. Among Sandeep's technical certifications are: IBM Certified e-business Solution Advisor, IBM Certified e-business Solution Designer, IBM Certified e-business Solution Technologist, IBM Certified Specialist - WebSphere Application Server , IBM Certified Systems Expert - WebSphere Application Server. You can contact Sandeep at sandeep@us.ibm.com.

Venkat Nagalla is an e-business Architect in IBM's Developer Relations Technical Consulting in Austin, Texas. Venkat works with both small and large IBM Business partners, helping to evangelize, educate and enable them on IBM's e-business platform. Venkat has 18 years of experience in the software engineering field with IBM. His areas of expertise include object-oriented design and development and, most recently, IBM WebSphere Business Components. Venkat holds IBM Certified e-business Solution Advisor and Sun Java Programmer certifications. You can contact Venkat at nagalla@us.ibm.com.
Comments (Undergoing maintenance)

