ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button
Programming Jakarta Struts

Jakarta Struts: Seven Lessons from the Trenches

by Chuck Cavaness, author of Programming Jakarta Struts
10/30/2002

Editor's note: After his Internet company decided to adopt the Struts framework, Chuck Cavaness spent months trying to figure out how to use it in order to build a company application. If you're a Java programmer charged with developing Web applications with servlets and JSPs, you'll find a lot of insight and valuable information in the lessons Chuck had to learn the hard way. He describes some of them here.

Introduction

The Jakarta Struts framework has only been around for a short time, but the impact it has made for Web developers is significant. The framework is based on widely accepted design patterns and is very extensible. Although the learning curve for Struts is manageable, there are still best practices when using the framework. These lessons become apparent during development of any medium- to large-size development project. However, a much faster way to get up to speed is to leverage lessons learned by others in the Struts community. Several of those lessons are offered here and are designed to increase your productivity and efficiency when building applications using Struts.

1. Extend When You Must

There are several characteristics of a good framework. One is that it must meet the needs of its intended audience. The Struts framework does this by providing a general infrastructure for building Web applications. This allows developers to focus more on solving the business problem. Another characteristic is that a good framework must provide extension points in the appropriate places to allow applications to extend the framework to better suit their needs.

It would be great if the Struts framework worked for every application in every situation. Realistically, no framework can make that claim. Some applications have requirements that can't be foreseen by the developers of a framework, and therefore the next best thing is to provide enough extension points where developers can twist and mold the framework to better fit their specific requirements.

Related Reading

Programming Jakarta Struts
By Chuck Cavaness

There are many places where the Struts framework can be stretched and customized to allow for customized behavior. Almost every configuration class in the Struts framework can be substituted for a customized version. This is accomplished by simple editing of the Struts configuration file. Other components such as the ActionServlet and RequestProcessor can also be replaced with a specialized version. Even the new features of Struts 1.1 are designed with extension in mind. The declarative Exception Handling mechanism for example, allows for custom exception handlers to be used to better respond to application failures.

The ability to pull and shape a framework to better suit your domain can have a dramatic impact on the outcome of a development project. First and foremost, since you are relying on an existing, mature, and stable framework like Struts, the number of defects found during testing should be reduced. You also can reduce the development time and number of required resources, since resources won't have to be spent on developing infrastructure code.

However, with this great power comes great responsibility. You must be careful not to overextend the application needlessly. There are many existing features spread throughout the framework classes, both in the core package and in the various utility packages that Struts relies on. Don't fall into the trap of extending the framework blindly without looking at other ways of doing the same thing with existing functionality. Make sure that when you decide to extend the framework that the functionality doesn't already exist somewhere else. Not doing so will result in redundant behavior and a bigger mess to clean up later.

2. Use Declarative Exception Handling

Specifying runtime behavior outside of the source code rather than hardcoding it within the application is almost always preferred; the world of J2EE is filled with examples of this. From the security and transactional behavior of Enterprise JavaBeans to the relationships between JMS messages and destinations, many of the runtime aspects can be declared outside of the application.

The Struts architects have taken this approach from the beginning by utilizing the Struts configuration file to specify runtime aspects of an application. That approach continues with the new 1.1 features, including the new exception-handling capabilities. In earlier versions of the framework, developers were left to their own devices when handling error situations that occurred in a Struts application. With the latest version, that's no longer the case. The framework includes a class called ExceptionHandler that by default is responsible for processing any exceptions that occur during action execution. As the previous tip on extending the framework mentioned, this is one of the many extension points that is available within the framework.

The default Struts exception handler class creates an ActionError object and stores it in the appropriate scope object. This allows the JSP pages to use the errors to inform the user of a problem. If this behavior does not fulfill your requirements, you are free to plug in one of your own ExceptionHandler classes.

Customizing the Exception Handling

To install your customized exception handler, the first step is to create a class that extends org.apache.struts.action.ExceptionHandler. There are two methods that you can override, execute() and storeException(). In most cases, however, you will just need to override the execute() method. The signature for the execute() method in the ExceptionHandler class is shown here:

public ActionForward execute( Exception ex, 
                              ExceptionConfig exConfig,
                              ActionMapping mapping,
                              ActionForm formInstance,
                              HttpServletRequest request,
                              HttpServletResponse response
  ) throws ServletException;

The method takes in several arguments, including the original exception, and returns an ActionForward object, which directs the controller as to where the request should be forwarded after the exception is dealt with.

You can perform whatever behavior you like, but generally you should inspect the exception that was thrown and do something based on the type of exception. Again, the default behavior is to create an error message and forward to the resource specified in the configuration file. An example of why you would want or need to customize this functionality is to support nested exceptions. Suppose the exception contained nested exceptions, and those exceptions also may contain other exceptions. You would need to override the execute() method to create error messages for each of these.

Once you have created your specialized ExceptionHandler class, you will need to inform the Struts framework to use your version instead of the default Struts exception handler. To do this, you will just need to declare your class in the Struts configuration file; this is the declarative part.

You can configure your ExceptionHandler to be used by certain Action mappings or by all Actions. For specific Action mappings, you include an <exception> element inside of the <action> element. To utilize the ExceptionHandler for all Action mappings, you can specify it inside the <global-sections> element. For example, suppose we want to use a customized exception handler called CustomizedExceptionHandler for all Action mappings. The <global-exceptions> element might look like this:

<global-exceptions>
  <exception
    handler="com.cavaness.storefront.CustomizedExceptionHandler"
    key="global.error.message"
    path="/error.jsp"
    scope="request"
    type="java.lang.Exception"/>
</global-exceptions>

There are various attributes that you can specify for the <exception> element. The most important of these, for this discussion, is the handler attribute. This attribute is the fully- qualified class name of the ExceptionHandler subclass. If this attribute is not specified, the framework will default to the one provided by the Struts framework. The other attributes are also important, but this one is of the utmost importance if you are trying to override the default behavior.

One final thing should be pointed out. You can have different exception handlers for different exceptions. In the example above, the CustomizedExceptionHandler was configured to process any exceptions that were children of java.lang.Exception. However, you can create multiple exception handlers, each one worrying about different exception trees. The following XML fragment shows how this can be configured:

<global-exceptions>
  <exception
    handler="com.cavaness.storefront.CustomizedExceptionHandler"
    key="global.error.message"
    path="/error.jsp"
    scope="request"
    type="java.lang.Exception"/>

  <exception
    handler="com.cavaness.storefront.SecurityExceptionHandler"
    key="security.error.message"
    path="/login.jsp"
    scope="request"
    type="com.cavaness.storefront.SecurityException"/>
</global-exceptions>

In this case, when an exception is thrown, the framework will attempt to find an ExceptionHandler configured for the exact match. If there's no exact match, the framework will proceed up the superclass chain of the exception until a match is found. With this approach, you can have a hierarchical relationship of handlers, and all of it declarative.

Pages: 1, 2, 3, 4

Next Pagearrow