Learning the New Jakarta Struts 1.1, Part 2

Editor's Note: This is part two of a two-part series on Jakarta Struts 1.1. The first part is available here. Portions of this article are excerpted from Sue Spielman's book, The Struts Framework: Practical Guide for Java Programmers (Morgan-Kaufmann), one of the first books on the market covering Struts 1.1 in detail. You can reach Sue at
.

Nested Tag Library

The whole point of having nested tags is that the tags can relate to each other and describe the structure of the model they're managing. The assumptions made by the tags simplify the necessary coding. Struts 1.0 developers can heave a sigh of relief knowing that they won't have to mangle code any longer to render a display of a list within a list.

The Struts nested tag library was introduced in Struts 1.1. Almost all of the tags in this library extend the base Struts tags that we've already talked about. This includes tags from the Html and Logic libraries, except they are prefixed with a nested namespace. So, for example, if we are nesting an <html:link> tag, we would use <nested:link> instead. There are also tags new to the nested tag library. The new tags include <nested:root> and <nested:nest>. The <nested:root> tag is used to indicate that you are starting a nested scope. This tag is used if <html:form> is not being used. The <html:form> (for backwards compatibility) or <nested:form> tags will automatically start a scope for you.

The difference between using non-nested tags as opposed to those from the nested library is that using the nested version allows the tags to relate to each other in a nested hierarchy. The fundamental logic of the original tags doesn't change, except that all references to beans and bean properties will be managed in a nested context using the dot notation that we have already seen when using properties. When building complex pages, it is highly likely that you will want to use the nested features. This makes pages much easier to write and maintain, since it allows for the logical flow to be maintained without having to do work-arounds, as was required before the 1.1 release.

Validator

The Validator framework is now part of the Struts package structure and can be found in org.apache.struts.validator. Why use the Validator framework? Validator makes life a bit easier when you have to deal with required fields; determining matches to a regular expression; email, credit card, and date validation; and server-side type checking.
This framework is based on the Commons Validator that can be found at jakarta.apache.org/commons.

The purpose is to perform server-side validations based on validation rules located in validation.xml. It is possible to add custom validations to this file. Rules can be defined for different locales. It's possible to store your specific Validator rules in a separate file. This is accomplished by setting the config-rules parameter in the ValidatorServlet contained in the web.xml file. The standard file is available in the Struts dist directory and is called validator-rules.xml.

Using this framework requires adding the ValidatorServlet to your web.xml file with its appropriate configuration parameters and then extending org.apache.struts.validator.action.ValidatorForm instead of org.apache.struts.action.ActionForm.

Validator is the first component to implement the new PlugIn interface in Struts 1.1, which we'll talk about next.

You can also add pluggable Validators by adding a validation method signature to your ValidatorAction class. For more details, see the org.apache.struts.validator.util.StrutsValidator class.

PlugIn API

A new feature of Struts 1.1 is the ablity to define a PlugIn. A PlugIn is a configuration wrapper for an application-specific module or service that must be notified about application startup and application shutdown events. These events correspond to the container calls init() and destroy() on the corresponding ActionServlet instance, which allows a module to be called without the need to subclass ActionServlet for simple Servlet lifecycle activities.

PlugIn modules can be configured in the struts-config.xml file, using the <plug-in> element. Classes that implement the PlugIn interface must supply a zero-argument constructor for use by ActionServlet. Configuration can be accomplished by providing standard JavaBeans property setter methods that will all have been called before the init() method was invoked. An instance of the specified class is created for each element, and can be configured with nested set-property elements. For example, in struts-config.xml we might have the last entry defined as:

This means that two instances of the ValidatorPlugIn will be created, each setting the property pathname to the appropriate value. By supporting the init() and destroy() methods of PlugIn, the ValidatorPlugin is notified about application startup and shutdown events without having to be concerned with extending ActionServlet code. PlugIns are configured in the struts-config.xml file by setting the plug-in element.

Declarative Exception Handling

Declarative exception handling allows for Actions to propagate exceptions. This feature is the very reason that the perform() method signature changed from throwing IOException and ServletException to just Exception. This is also why we see the execute() method of an Action called by the ActionServlet. One reason for going this route is so your Actions don't have to think about each and every exception that might be thrown from your business logic. It also allows exceptions to be configured within the struts-config.xml file.

Declarative exception handling is accomplished in two ways. One is by configuring <global-exceptions> in the struts-config.xml file. The other is by using the exception element of <action>, which describes a mapping of an exception that may occur during Action delegation.

The way that the exceptions are declared is very similar to the way that <global-forwards> and <forwards> are declared. A <global-exceptions> configures the global handling of exceptions thrown by Actions to mappable resources using an application-relative URI path. This can be a specific page designed to handle this exception.

It is also possible to override an exception handler declared in the global setting by using the exception element in the action, which uses the same type attribute as defined in the global setting. You can specify the className attribute, which indicates the implementation subclass of the standard configuration bean. The default class is:

org.apache.struts.config.ExceptionConfig

The handler attribute is the fully-qualified Java class name of the exception handler that should handle this exception. The default is org.apache.struts.action.ExceptionHandler.
The key attribute is the message resources key specifying the error message associated with this exception. This is helpful in keeping your errors friendly when your application is internationalized.