Take command of your software

The Command pattern benefits both the client and the server

If you've been developing software long enough, you might recall a time before object-oriented (OO) development went mainstream when software development proved much more difficult than it is today. In those days, developers wrote software using archaic function libraries to develop applications entirely from scratch, using low-level functions from those libraries to develop software systems. For the fruits of their labors, developers produced software such as Microsoft Windows 3.1, which ever since has been known as the poster boy for clunky software that crashed soon after your last reboot.

Today, of course, things have improved considerably. Instead of Windows 3.1, we now have Windows XP, a vast improvement over its predecessors, and other software marvels, such as the amazing Mac OS X. Many factors contributed to the increase of software productivity and reliability over the years, but the overriding factor has been the widespread adoption of OO design and development, which turned the paradigm of developing software from scratch with function libraries completely inside-out. With OO design, developers employ application frameworks that provide the majority of an application's code and implement applications by plugging reusable components into those frameworks.

In the early days, when application frameworks first appeared, developers faced a major hurdle. Application frameworks must issue requests to application-specific objects without knowing anything about those objects or the operations they perform. For example, the Swing application framework issues requests to objects when menu items are activated or buttons are pressed. Swing can't implement those requests because they are application-specific. So how does an application framework like Swing issue requests to objects without knowing anything about the requested operation or the objects themselves? The answer: the Command design pattern.

In this article, I discuss the Command pattern, sometimes known as the Action pattern, from two different perspectives. First, I show how the Command pattern works in client-side Java with Swing's implementation of the Command pattern for menu items. Second, I discuss how the Command pattern works in server-side Java to parameterize HTTP requests with the Apache Struts JSP (JavaServer Pages) framework. Along the way, you will learn a bit about Swing, Struts, and the newest kid on the server-side Java block, the JSP Standard Tag Library (JSTL).

Note: You can download this article's example source code from Resources.

The Command pattern

In Design Patterns, the authors define the Command pattern as:

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

By implementing commands as objects, the Command pattern lets application frameworks invoke methods of application-specific commands. Figure 1 shows a Command pattern class diagram.

Figure 1. Command pattern class diagram

In Figure 1, the Invoker class represents an object in an application framework, such as a button or menu item. The Invoker maintains an association with a command through a reference to an object that implements a Command interface, which defines an execute() method. Concrete command classes implement that interface, typically by using an object known as a receiver—application-specific objects that carry out the request. Figure 2 shows a Command pattern sequence diagram.

Figure 2. Command pattern sequence diagram

At runtime, the Invoker calls the Command's execute() method, and the Command invokes a Receiver's method—modeled here as an action() method—that carries out the request.

Swing actions

Almost all OO application frameworks implement the Command pattern, and Swing is no different. This section illustrates how Swing uses the Command pattern to perform application-specific functionality tied to Swing buttons serving as the building blocks for other components, such as menu items or toolbar buttons.

Swing implements the Command pattern with action objects. Whenever you select a Swing menu item or activate a Swing button, those action objects issue a request to an application-specific action. Figure 3 shows a class diagram for Swing actions and how they relate to buttons and menus.

Figure 3. Swing actions class diagram. Click on thumbnail to view full-size image.

Buttons, defined by the AbstractButton class, serve as the Swing workhorses. For simplicity's sake, Figure 3's class diagram does not show all of the classes that ultimately extend AbstractButton because there are many AbstractButton ancestor classes. (Note: Figure 3 also omits most of the AbstractButton methods.) Swing buttons, radio buttons, toggle buttons, check boxes, menus, menu items, check-box menu items, and radio-button menu items are all AbstractButton class extensions. That class maintains a reference to an action defined by the Action interface. You can set or get that reference with the AbstractAction setAction() and getAction() methods, respectively.

Whenever one of the aforementioned Swing components activates, it calls its action's actionPerformed() method, which implements some application-specific functionality. As a convenience, Swing's AbstractAction class eases the implemention of application-specific actions. Let's see how.

Figure 4 shows a Swing application with a single menu featuring two menu items: "show dialog" and "exit." When you activate the "show dialog" menu item, as depicted in Figure 4's top picture, an application-specific action displays the dialog box shown in Figure 4's bottom picture. When you activate the "exit" menu item, another application-specific action terminates the application.

Figure 4. Swing actions in action

The application shown in Figure 4 is listed in Example 1:

Example 1. Two simple Swing actions

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test extends JFrame {
   public static void main(String args[]) { 
      Test frame = new Test();
      frame.setTitle("Swing Actions");
      frame.setSize(500, 400);
      frame.setLocation(400, 200);
      frame.show();
   }
   public Test() {
      JMenuBar mb = new JMenuBar();
      JMenu fileMenu = new JMenu("File");
     fileMenu.add(new ShowDialogAction());
      fileMenu.add(new ExitAction());

      mb.add(fileMenu);
      setJMenuBar(mb);
   }
}
class ShowDialogAction extends AbstractAction {
   public ShowDialogAction() {
      super("show dialog");
   }
   public void actionPerformed(ActionEvent e) {
      JOptionPane.showMessageDialog((Component)e.getSource(),
                               "An action generated this dialog");
   }
}
class ExitAction extends AbstractAction {
   public ExitAction() {
      super("exit");
   }
   public void actionPerformed(ActionEvent e) {
      System.exit(0);
   }
}

The preceding application implements two actions—ShowDialogAction and ExitAction—both of which extend the AbstractAction class. Those classes implement their actionPerformed() methods to implement application-specific functionality; namely, showing a dialog and exiting the application, respectively. The application creates a file menu that's a JMenu class instance and passes instances of ShowDialogAction and ExitAction to that menu's add() method. The add() method creates a menu item—a JMenuItem instance—and associates the action it is passed with the newly created menu item by invoking the menu item's add() method, inherited from AbstractAction, as Figure 3 shows. From then on, the menu items and their actions are wired together: when the menu item is selected, it invokes its action's actionPerformed() method. That method is passed an action event, which provides information about the event, including the component that generated the event. The ShowDialogAction.actionPerformed() method uses that component to create a message dialog. (The ExitAction.actionPerformed() method has no use for the action event it is passed because it simply exits the application.)

The Swing Command pattern implementation closely adheres to the classic pattern's description in Design Patterns. In Swing, an invoker (in this case a menu item) maintains a reference to a command (in this case an action). That reference points to a command's abstract definition (the AbstractAction class), so that the command can represent any application-specific command (in this case a class that extends AbstractAction). When a trigger event occurs (in this case the menu item is selected), the invoker sends a request to the command and the command implements its application-specific functionality.

Now that we've discussed a classic Command pattern implementation for client-side Java, let's take a look at another Command pattern implementation for server-side Java that deviates a bit from the classic Command pattern definition.

Struts actions

Struts, a popular open source JSP application framework from the Apache Software Foundation, implements numerous design patterns, including the Model-View-Controller (MVC) pattern and, of course, the Command pattern. By applying design patterns to server-side Java components, such as servlets and JSPs, Struts makes it simple to implement modular, easily maintainable, and extensible Web applications.

Struts comprises numerous pieces of distinct functionality, including JavaBean utilities, an XML digester, a database connection pool, and a comprehensive set of JSP custom tags. But the most significant cog in the Struts wheel is an MVC framework that revolves around the Command pattern. The rest of this article outlines that framework with a simple Web application.

All Web applications, at their core, perform the same basic function: field HTTP requests and respond to those requests by performing some application-specific functionality. Struts provides a servlet—known as the action servlet—that handles HTTP requests and ultimately invokes an application-specific action. The Struts action servlet turns HTTP requests into actions, but as a developer employing Struts to implement Web applications, you can remain blissfully ignorant of how it works—that's the beauty of application frameworks and the Command pattern. You simply need to know how to map an HTTP request to a Struts action, how to implement that action, and you're off and running. Figure 5 shows a Struts-actions class diagram and how those actions relate to the action servlet.

Figure 5. Struts actions class diagram. Click on thumbnail to view full-size image.

Struts actions typically extend the Action class. Struts also provides Action subclasses you can extend for special-needs actions. For example, you can extend the DispatchAction class for actions that combine a set of similar actions in a single action class. In this article, I examine a simple action implementation that directly extends the Action class.

Every Struts action maintains a reference to the action servlet, which is handy for accessing various servlet properties; for example, you can obtain a reference to your Web application with the action servlet's getServletContext() method. You can use that application to access application attributes, as you'll see shortly.

Now that you have a cursory understanding of Struts, let's dive in deeper by examining the simple Web application shown in Figure 6.

Figure 6. Use Struts actions

Figure 6's Web application consists of two JSPs: test.jsp, shown in the top picture and forwardPage.jsp, shown in the bottom two pictures. When you click on the link in test.jsp, an HTML anchor element sends an HTTP request to the Struts action servlet. The action servlet maps that request to an application-specific action that increments a counter stored in a file, and subsequently forwards to forwordPage.jsp. That JSP displays the counter's value and includes test.jsp so that you can initiate the request/action cycle again if you desire.

To implement Figure 6's Web application, first configure the application in the deployment descriptor, as seen in Example 2:

Example 2. WEB-INF/web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
  PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
  "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
<web-app>
  <!-- Action Servlet Configuration -->
  <servlet>
    <servlet-name>
       action
    </servlet-name>
    <servlet-class>
      org.apache.struts.action.ActionServlet
    </servlet-class>
    ...
    <init-param>
      <param-name>config</param-name>
      <param-value>/WEB-INF/action.xml</param-value>
    </init-param>
    ...
  </servlet>
  <!-- Action Servlet Mapping -->
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
  ...
</web-app>

The preceding deployment descriptor does three things:

  1. Maps the name action to the Struts action servlet (org.apache.struts.action.ActionServlet)
  2. Creates an initialization parameter for the action servlet that specifies a Struts configuration file (/WEB-INF/action.xml)
  3. Maps all URLs that end in .do to the action servlet

Example 3 lists test.jsp, the JSP shown in Figure 6's top picture:

Example 3. test.jsp

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
   <head>
     <title>Struts Actions</title>
   </head>
   <body>
     <a href='simple.do'>
       Click Here to Perform a Simple Action
     </a>
   </body>
</html>

The preceding JSP creates an HTML anchor element that references the /simple.do URL. If you click on that link, the Struts action servlet is invoked because the mapping in the deployment descriptor maps all URLs that end in .do to the action servlet (see Example 2). So what does the action servlet do when it receives the /simple.do URL? The answer resides in the Struts configuration file, which is specified in the deployment descriptor (see Example 2) and listed in Example 4:

Example 4. WEB-INF/action.xml

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
  "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"
  "http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd">
<struts-config>
   <action-mappings>
      <action path="/simple"
              type="actions.SimpleAction">
         <forward name="fwd-page" path="/forwardPage.jsp"/>
      </action>
   </action-mappings>
</struts-config>

The preceding configuration file maps the /simple URL to the actions.SimpleAction class. When the action servlet receives the /simple.do URL, it strips off the .do suffix and maps the URL to the actions.SimpleAction class. If an instance of that class does not exist, the action servlet creates one and invokes its execute() method. Example 5 lists the actions.SimpleAction class:

Example 5. WEB-INF/classes/actions/SimpleAction.java

package actions;
import javax.servlet.ServletContext;
import javax.servlet.http.*;
import org.apache.struts.action.*;
import beans.CounterBean;
public class SimpleAction extends Action {
     public ActionForward execute(ActionMapping mapping, 
                                ActionForm form,
                                HttpServletRequest request, 
                                HttpServletResponse response)
                  throws java.io.IOException, 
                         javax.servlet.ServletException {
      ActionServlet      servlet = getServlet();
      ServletContext application = servlet.getServletContext();
      CounterBean    counterBean = (CounterBean)application.
                                     getAttribute("counterBean");
      if(counterBean == null) {
         counterBean = new CounterBean();
         application.setAttribute("counterBean", counterBean);
      }
      counterBean.updateCount(request, ".simpleActionCount");
      return mapping.findForward("fwd-page");
   } 
}

The preceding action checks to see if a counter bean exists in the application scope; if not, it creates one and stores it there. Subsequently, the action invokes the counter bean's updateCount() method, which updates a counter stored in a file named .simpleActionCount. Then the action returns an ActionForward instance that points to a JSP mapped to the string fwd-page. That mapping, also defined in the Struts configuration file (see Example 4), resolves the string fwd-page to the forwardPage.jsp JSP. The action servlet subsequently forwards control to that JSP, listed in Example 6:

Example 6. forwardPage.jsp

<%@ taglib uri='/WEB-INF/tlds/struts-bean.tld' prefix='struts'%>
<%@ taglib uri='http://java.sun.com/jstl/core' prefix='c'%>
<%@ page import='beans.CounterBean' %>
This simple action has been accessed 
<c:out value='${counterBean.count}'/> 
<c:choose>
   <c:when test='${counterBean.count == 1}'>
      time.
   </c:when>
   <c:otherwise>
      times.
   </c:otherwise>
</c:choose>
<p><c:import url='test.jsp'/>

The preceding JSP uses the JSTL <c:out>, <c:choose>, <c:when>, and <c:otherwise> actions to display information about how many times the counter bean, and therefore the simple action, has been accessed. JSTL defines an expression language that will be incorporated into the upcoming JSP 2.0. The preceding JSP, for example, uses that expression language to access the counter bean in application scope. (You can download JSTL from Resources.)

Finally, Example 7 lists the counter bean class—beans.CounterBean:

Example 7. WEB-INF/classes/beans/CounterBean.java

package beans;
import java.io.*;
import javax.servlet.http.*;
public class CounterBean {
   private int count = 0;
   private File file = null;
   public synchronized void updateCount(HttpServletRequest request,
                                        String filename) 
                                       throws java.io.IOException {
      checkFile(filename);
      readCount();
      count++;
      saveCount();
   }
   public int getCount() {
      return count;
   }
   private void checkFile(String filename) throws IOException {
      if(file == null) {
         file  = new File(filename);
         count = 0;
      }
      if(!file.exists()) {
         file.createNewFile();
         saveCount();
      }
   }
   private void saveCount() throws java.io.IOException {
      FileWriter writer = new FileWriter(file);
      writer.write(count);
      writer.close();
   }
   private void readCount() throws java.io.IOException {
      FileReader reader = new FileReader(file);
      count = reader.read();
      reader.close();
   }
}

The CounterBean class updates the count associated with a particular action. That class serves as a receiver, as I discussed at this article's beginning, by implementing application-specific behavior.

Your wish is my command

Unless you develop application frameworks, you may never need to implement the Command pattern; nevertheless, you should understand how it works so you can effectively use application frameworks such as Swing and Struts. Now that you've seen how to use the Command pattern in Swing and Struts, you'll be able to better use those and other OO frameworks you encounter in the future.

Homework

For your homework assignment, download Struts, then add your own custom action to the example discussed above. That custom action can implement whatever application-specific behavior you desire.

Homework from last time

In your homework assignment from "Strategy for Success" (JavaWorld, April 2002), I asked you to discuss how Swing uses the Strategy pattern in its list class to render list cells.

As "Strategy for Success" outlined, the Swing JComponent class uses the Strategy pattern to paint borders around components. The JComponent class also uses the Strategy pattern to paint Swing components themselves by delegating that behavior to individual Swing components; for example, the JComponent.paint() method invokes the paintComponent() method, which JComponent subclasses override to paint the component.

Some Swing components, those with more complicated rendering needs, do not paint themselves; instead, they use the Strategy pattern to delegate that behavior to another object. For example, Swing lists delegate the painting of their list cells to an object that implements the ListCellRenderer interface. That interface defines a single method—getListCellRendererComponent()—that returns a component that paints the list's cells. That Strategy pattern usage lets developers modify how lists paint their cells by implementing a list cell renderer and attaching it to a specific list.

David Geary is the author of Core JSTL Mastering the JSP Standard Tag Library, which will be published this fall by Prentice-Hall and Sun Microsystems Press; Advanced JavaServer Pages (Prentice Hall, 2001; ISBN: 0130307041); and the Graphic Java series (Sun Microsystems Press). David has been developing object-oriented software with numerous object-oriented languages for 18 years. Since the GOF Design Patterns book was published in 1994, David has been an active proponent of design patterns, and has used and implemented design patterns in Smalltalk, C++, and Java. In 1997, David began working full-time as an author and occasional speaker and consultant. David is a member of the expert groups defining the JSP standard custom tag library and JavaServer Faces, and is a contributor to the Apache Struts JSP framework.

Learn more about this topic

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