6.1 Release Notes - Version 1.3.1

SPECIAL NOTE ON UPGRADING - README FIRST! - If you use the standard CANCEL BUTTON in your application and validate is set to true for that mapping, you MUST also specify "cancellable=true" in the mapping, otherwise, an InvalidCancelException will be thrown if the Cancel button is used. See the new Opt-In Cancel Handling feature for more.

                        <action path="/ActionThatCanBeCancelled"
                                validate="true"
                                cancellable="true"
                                ...
                         </action>
                    

Introduction

This section contains release notes for changes that have taken place to the seven new subprojects known as "Struts Classic" since Version 1.2.9 . To keep up-to-date on all changes to Struts, subscribe to the (commits at struts.apache.org) list. To preview our plans for upcoming changes, please visit the Roadmap page .

Notes on upgrading are maintained in the Wiki Upgrade pages . The wiki is a community maintained resource - please feel free to add your input so that everyone can benefit from the collective experience.

For the version requirements of each library, see the Installation chapter .

Highlights of Changes

The purpose of this section is to highlight the new features since the Version 1.2.8 release. For more detail, see the Project Info reports for each subproject, which include a complete changelog and list of external dependencies.

You can also access to the Apache Struts source repository and change logs directly through both web browser and Subversion client interfaces.

People

On the volunteer front, eight new committers accepted invitations to join us. We welcome Wendy Smoak , Gary VanMatre , Sean Schofield , Greg Reddin , Laurie Harper , Richard Feit , Jason Carreira , and Patrick Lightbody .

We also welcome Wendy Smoak and Gary VanMatre to the Apache Struts PMC (Project Management Committee).

Struts Library

Since Struts 1.2.8, we have subdivided Struts into several subprojects, each with its own release cycle. The set of seven subprojects derived from Struts 1.2 is sometimes referred to as "Struts Classic". The Struts Classic subprojects are Action, Applications, EL, Extras, Site, Taglibs, and Tiles. These subprojects will all inherit version 1.3.0, but, thereafter, subproject revisions will increment independently of each other.

Since many teams will use Struts with one or more extensions, we are bundling the jars for extensions that utilize the framework into a single distribution called "Struts Library".

The Apache Struts subprojects, including the website, are being built with Maven. But, of course, you can continue to build your own projects any way you like!

Dependency Changes

Specification Changes

The 1.3.x series of Struts now has a minumum requirement of the following specification versions:

  • Java Servlet 2.3 and JavaServer Pages (JSP) 1.2
  • Java 2 Standard Platform Edition (J2SE) 1.4

Software Component Changes

A number of software dependency changes apply to this release:

Struts Applications

The applications have been moved into their own subproject, the builds have been "Mavenized", but the set of example applications is essentially unchanged.

  • In MailReader, fix invalid password limit error.
  • The examples application's config files (struts and validation) in the Validator module have been split into up into one per example page.
  • In all applications, update configuration for new cancellable property as needed.

Struts

Major changes to the framework include

  • Composable Request Processor
  • Arbitrary configuration properties
  • Catalog and Command Elements
  • Opt-In Cancel Handling
  • Enhanced Global Exception Handlers
  • Extends attribute
  • "isCommitted" Exception Handling
  • Postback Actions
  • Wildcard ActionConfig properties

Composable Request Processor

In prior versions, the request processing guantlet is represented as a series of methods. While it was easy to override the methods to provide different functionality, it was not easy to use multiple extension that each wanted to override the request processor in a different way.

                    public void process(HttpServletRequest request,
                    HttpServletResponse response)
                    throws IOException, ServletException {

                    processLocale(request, response);
                    if (!processRoles(request, response, mapping)) {
                    return;
                    }
                    /// ...
                    ActionForward forward =
                    processActionPerform(request, response,
                    action, form, mapping);
                    processForwardConfig(request, response, forward);
                    }
                

For Action 1.3, we turned the request processor methods into Commands that are part of a flexible Chain of Commands. Rather than subclassing a monolithic object, we can now just replace Commands. Commands can also be inserted or removed, if needed, to extend or streamline the request processing gauntlet to meets the needs of different kinds of applications.

                    <chain name="process-action">
                    <command className= "...SelectLocale"/>
                    <command className= "...AuthorizeAction"/>
                    <!-- ... -->
                    <command className= "...CreateAction"/>
                    <command className= "...ExecuteAction"/>
                    </chain>
                

We fully expect the Action 1.3 request processor to be backwardly compatible with earlier versions. But, to be prudent, we wanted to release 1.3 with the Composable Request Processor before making additional changes.

We've made a few other changes and improvements in Action 1.3.x, but the two big-ticket items are subprojects and the new request processor.

If needed, the monolithic RequestProcessor from Struts 1.2 is still available in the distribution and may be configured via the controller element.

                    <controller
                    processorClass="org.apache.struts.action.RequestProcessor"
                    />
                

However, we consider this RequestProcessor to be a legacy class. Once the new ComposableRequestProcessor is more-widely field tested, we expect that this class will be deprecated, moved to the Extras subproject, and ultimately removed. Accordingly, some new features, like Opt-In Cancel Handling, are only supported by the new Composable Request Processor.

Arbitrary configuration properties

Most every Struts configuration element now accepts a map of key/value pairs. Arbitrary configuration properties let us externalize more of our configurations, encouraging reuse.

                    <action path="/EditSubscription"
                    extends="Editor">
                    <set-property key="foo" value="bar"/>
                    </action>

                    public ActionForward execute(
                    ActionMapping mapping,
                    ActionForm form,
                    HttpServletRequest request,
                    HttpServletResponse response)
                    throws Exception {
                    string foo = getProperty("foo");
                    // ...
                

Arbitrary Configuration should make it easier for everyone to write reusable chunks of code, for ActionMappings, Exception Handlers, and other members.

Opt-In Cancel Handling

SPECIAL NOTE ON UPGRADING - README FIRST! - If you use the standard CANCEL BUTTON in your application and validate is set to true for that mapping, you MUST also specify "cancellable=true" in the mapping, otherwise, an InvalidCancelException will be thrown if the Cancel button is used. Here's why:

In Struts 1.2.8 and prior, any time the magic token generated by the Cancel tag is found in the request, validation for the ActionForm is skipped. Accordingly, in Struts 1.2.8 and prior, any Action that relies on validation should always observe the isCancelled method.

In Struts 1.3, the Cancel token is only honored if the new property "cancellable" is set for the Action Mapping. If the Cancel token is present, but cancellable is not set, then an InvalidCancelException is thrown. The InvalidCancelExeption may be caught by a Declarative Exception Handler, like any other Exception.

                        <action path="/ActionThatCanBeCancelled"
                                validate="true"
                                cancellable="true"
                                ... >
                        <exception
                                key="errors.invalidCancel"
                                type="org.apache.struts.action.InvalidCancelException"
                                path="/InvalidCancelException.jsp"/>
                         </action>
                    

The declarative exception handler is optional. The Exception will only be thrown when there is a programming error or when a rogue client is trying to bypass validation.

Note that the Opt-In Cancel Handler is available for the Composable Request Processor as well as the legacy Request Processor included in Struts 1.3.

Enhanced Global Exception Handlers

We now support use of global exception handlers in cases when no ActionConfig has yet been identified, as in with "preprocessing" commands in a custom request processing chain. In the case when there is no ActionConfig, the AbstractExceptionHandler will now call a new method in ModuleConfig which provides similar logic for finding a globally mapped exception handler for the given exception class or any of its superclasses.

Catalog and Command elements

Available for both the Controller and any Action Mapping

catalog - The name of a commons-chain catalog in which to look up a command to be executed as part of servicing this request. Only meaningful if "command" is also specified.

command - The name of a commons-chain command which should be looked up and executed as part of servicing this request.

                    <controller
                    inputForward="true"
                    catalog="Foo"
                    command="FooBar"
                    />
                

Extends attribute

In the Struts configuration file, we can now use the extends attribute to adopt default settings from another element, as we already can in the Tiles configuration files.

                    <struts-config>
                    <form-beans>
                    <form-bean name="registrationForm"
                    type="org.apache.struts.action.DynaValidatorForm">
                    <form-property name="firstName" type="java.lang.String"
                    />
                    <form-property name="lastName" type="java.lang.String"
                    />
                    </form-bean>

                    <form-bean name="managerRegistrationForm"
                    type="org.apache.struts.action.DynaValidatorForm"
                    extends="registrationForm">
                    <form-property name="department"
                    type="java.lang.String" />
                    </form-bean>
                    </form-beans>
                    ...
                    </struts-config>
                

Extends makes using XML elements much more like object-orientated programming. You can setup a base element, and then only specify the behavior that changes. Extends lets us set default values and then "program by difference". When elements are not relentlessly chanting the same things over and over, it's easier to see the forest for the trees.

"isCommitted" Exception Handling

When using Tiles, sometimes the response is already committed when an exception occurs. Now, the ExceptionHandler tests response.isCommitted , and, if true, includes the configured view path, rather than forwarding to it. The updated ExceptionHandler accepts new configuration attributes which let you choose alternate behavior, or no behavior at all. See the JavaDoc for details.

                    <exception
                    key="GlobalExceptionHandler.default"
                    type="java.lang.Exception"
                    path="/ErrorPage.jsp">
                    <set-property key="INCLUDE_PATH" value="/error.jsp"/>
                    </exception>

                    <exception
                    key="GlobalExceptionHandler.default"
                    type="java.lang.Exception"
                    path="/ErrorPage.jsp">
                    <set-property key="SILENT_IF_COMMITTED" value="true" />
                    </exception>
                

Postback Forms

The action attribute of the Form taglib is now optional. If omitted, the original URI of the original request is used.

                    <html:form
                    onsubmit="return validateLogonForm(this);">
                

Wildcard ActionConfig properties

Wildcards can now be used in the properties of an ActionConfig. This makes it easier to pass multiple request-time values to the Action without complicating the "parameter" attibute.

                    <action path="/Save*"
                    name="Save{1}"
                    extends="BaseSave">
                    <set-properties key="Save" value="{1}"/>
                    </action>
                

Other Miscellaneous Changes

  • Added support for resetting DynaActionForm property values through configuration.
  • Changed the MultipartRequestWrapper to extend the HttpServletRequestWrapper which was introduced in Servlet 2.3. This fixed the issue that MultipartRequestWrapper didn't support Servlet 2.4 methods and means that mutlipart requests no longer have to be "un-wrapped" before forwarding - now making parameters parsed from the multipart request available after forwarding.
  • Added support for per-field character encoding in multipart requests.
  • Resolved Bug 38534 DOS attack, application hack.

Struts EL

Aside from addressing deprecations, there were a few minor changes to Struts EL.

  • Remove reference to html:html's locale attr in TestELHtmlTag
  • Fixed the "errorKey" being set incorrectly set to null in the release() method (for HTML form field tags).
  • Added "onselect" attribute to TextTag and TextareaTag.

Struts Extras

This subproject was extracted from the Actions and Plugins packages of Struts 1.2. The code itself is unchanged except for one minor issue.

  • ModuleConfigVerifier has been modified to use Commons Logging in line with the rest of Struts.

Struts Site

The new Site subproject hosts the top-layer of the Struts website, and serves as a portal to the other subprojects.

Struts Taglibs

We're changed the way we generate our reference documentation for the taglibs, but we think you will find the new reference just as useful as the old. Otherwise, we made only minor fixes to the trusty Struts Taglibs.

  • Update error message for when value is null to specify the id of the bean being defined.
  • Updated tag to filter value field to prevent it from breaking HTML if the value has reserved characters in it.
  • Changed logic so that the "must specify only one of..." message only get's thrown if the user is specifying more than one of the available options. The code was throwing the message if the user didn't specify any at all and should be flowing down to the "no value specified" error message. Update "can contain only one of..." message to specify which bean has the error.
  • Update FormTag to provide better debug message in the scenario where an action mapping is missing a form bean name.
  • Update TagUtils to provide a more specific error message in the case where properties on a formbean are not found. Basically this change handles the scenario where the Constants.BEAN_KEY value was being displayed as the bean name. Now, the actualy bean name will be displayed.
  • Changing rendering of the form name to use the 'id' attribute when in in XHTML strict mode. If an 'id' is already identified with the 'tyleId' attribute, an exception is thrown.
  • Changed dynamic focus javascript to choose form using 'id' attribute in XHTML mode
  • Changed the "action" attribute of the Form taglib to be optional. If omitted, the original URI of the request is used.
  • Filter anchors out when determining action mapping name.
  • Fix MessagesTag so that non-resource messages are possible for multiple messages, instead of just the first one.
  • Fix MessagesTag so that it displays an error message if a resource key is not found rather than throwing a NullPointerException.
  • Added escape for single quotes and new lines in javascript values.
  • Fixed the mis-leading warning message indicating a missing form when dynamicJavascript is false in the JavascriptTag.
  • Added "onselect" attribute to TextTag and TextareaTag (standard and nested versions).
  • Fixed indexed behaviour to check for JSTL's LoopTag rather than LoopTagSupport to verify JSTL.

Struts Tiles

Tiles is being refactored into a standalone package that can be used with or without Struts. For more on how this affects Tiles users, see the Tiles subproject site.

Next: Installation