Display Errors

Almost invariably, web applications generate validation errors at some point. And the user has to be told that they did something wrong, and what they should do about it. Hopefully this should be consistent with your applications UI guidelines, and make it clear to the user how to proceed. This how-to explains the tools available in Stripes to help you.

Outputting Errors

Stripes provides a number of tags to output validation errors, and it is worth taking the time to read the tag library documentation for them. The main tag is stripes:errors. This tag can output all the validation errors for a form, or output the errors only for a single field.

I won't repeat the tag documentation here (go read it already!), but here are a couple of examples:

Example 1: Outputting all errors with default formatting
<stripes:errors/> 

The above example will, assuming it is not nested inside a <stripes:form> tag, output all the validation errors in an HTML unordered list, for whatever form was posted. If you have more than one form on the page, you can display the errors for each in different places:

Example 2: Multiple forms outputting errors in different locations
<stripes:form action="/foo/first.action"> 
    <stripes:errors/> 
    ... 
</stripes:form> 

... 

<stripes:errors action="/foo/second.action"> 
<stripes:form action="/foo/second.action"> 
    ... 
</stripes:form> 

The first <stripes:errors/> tag is nested inside a <stripes:form> tag. When this occurs, the errors tag will only output errors if they are the result of posting the form in which it is contained. The second <stripes:errors/> tag is not nested inside a form, but since it is supplied an action attribute, it will only display errors if they are the result of submitting a form with an action matching the value supplied to the errors tag.

The next example shows how to ouput errors for a single field at a time, and output global errors (those not associated to any specific field) separately:

Example 3: Outputting errors by field
<stripes:form action="/foo/fist.action"> 
    <stripes:errors globalErrorsOnly="true"/> 

    <table> 
        <tr> 
            <td>Username:</td> 
            <td> 
                <stripes:text name="username"/> 
                <stripes:errors field="username"/> 
            </td> 
        </tr> 
        <tr> 
            <td>Password:</td> 
            <td> 
                <stripes:text name="password"/> 
                <stripes:errors field="password"/> 
            </td> 
        </tr> 
    </table> 
</stripes:form> 

The default output format for errors is controlled using a set of four resources from the error messages bundle (usually StripesResources). A different set of resources is used when outputting field specific errors to allow distinct presentation. This is documented in more detail in the tag documentation for the errors tag. The format can also be modified on a per-use basis by nesting tags including the individual-error tag inside of the errors tag.

Highlighting the field(s) in error

Stripes also has the ability to modify the rendering of fields that are in error. It does this using a class that implements TagErrorRenderer, which is supplied by a factory class that implements TagErrorRendererFactory. In a few minutes we'll cover what you can do by providing your own implementations of these classes. But first, lets look at what the default classes do.

Changing style with the default TagErrorRenderer

Firstly, there is the DefaultTagErrorRendererFactory which is extremely simple - it returns an instance of DefaultTagErrorRenderer. It can also be configured to return instances of other renderers you might write.

The DefaultTagErrorRenderer is also quite simple. It makes a single change to any field in error; it changes the tag's CSS style. If the tag did not have a class="something" attribute, then the default error renderer adds one, giving class="error". If the tag had a class attribute, say class="foo", then the renderer will rewrite that as class="error foo" which says that the error class has precedence, but anything it doesn't specify may then be specified by the foo class.

It may at first seem a little limiting to have only a single class name for displaying all form fields in error. What if you want to display graphical widgets like selects, check boxes and radio buttons differently from textual widgets like text and textareas? Well, if you asked that question, then it's time to learn a little (more) CSS. CSS selectors allow you to specify styles (with the same name) that select different tags based on all sorts of properties. Probably the most useful in this scenario is the attribute selector. The following shows how to use attribute selectors to apply a global error style to input fields, and then specific changes for some types.

Using selectors to specify error classes
input.error, textarea.error { 
    color: red; 
    background-color: yellow; 
} 

input.error[type="radio"], input.error[type="checkbox"], select.error { 
    background-color: white; 
    border: 2px solid red; 
} 

Using selectors, you could:

  • Specify a different style for every type of input field
  • Specify different styles for when a field is empty vs. has a value that is wrong
  • Specify styles based on fields' position within an HTML layout

    CSS Selector Reference

    The following web page is an excellent reference on CSS selectors: http://www.w3.org/TR/REC-CSS2/selector.html.

Using custom TagErrorRenderers

We've seen that using CSS we can change the appearance of error fields quite significantly. But there are probably some things that we can't do with CSS - or at least would find very very difficult. Perhaps you'd like to put a little red * next to fields in error, or a warning icon (warning), or maybe even a little message like "<<< Hey Moron, error over here". Well, maybe that last one is going a bit far, but who knows what your users want! All of the above, and more, can be done by implementing your own TagErrorRenderer.

Actually the first step is to determine how many TagErrorRenderer implementations you need. In most cases it will probably be just one, but when the TagErrorRendererFactory is asked for a TagErrorRenderer, it is supplied with the instance of InputTagSupport (the base class for all Stripes' input tags) that is in error. That gives you the information you need to provide different error renderer implementations (or just differently configured instances) based on the type of tag supplied, the tag's attributes, or information about the tag's containing tag and so on.

Let's assume for now that we stick with a single TagErrorRenderer, and that our goal is to ouput a red asterisk next to the field. The first thing we'll need to do is to implement a TagErrorRenderer.

A custom TagErrorRenderer
public class CustomTagErrorRenderer implements TagErrorRenderer { 
    private InputTagSupport tag; 

    /** Store the tag that is in error. */ 
    public void init(InputTagSupport tag) { 
        this.tag = tag; 
    } 

    /** Output our asterisk before the tag/field itself is rendered. */ 
    public void doBeforeStartTag() { 
        try { 
            this.tag.getPageContext().getOut().write 
                ("<span style=\"color:red; font-weight:bold;\">*</span>"); 
        } 
        catch (IOException ioe) { 
            // Not really a whole lot we can do if writing to out fails! 
        } 
    } 

    /** Doesn't need to do anything. */ 
    public void doAfterEndTag() { } 
} 

Change and Change Back

If you modify the state of the tag in a TagErrorRenderer, it is important that at the end of doAfterEndTag() you take steps to restore the tag to it's original state. This is because many modern
Servlet/JSP containers pool custom tags, and they will expect the tag to be in the same state it was after the container finished invoking setter methods on it. If you changed anything, and forgot to change it back, this won't be true - and you might start seeing weird bugs in your JSPs.

Now that we have our own TagErrorRenderer we have to tell Stripes to use it. The easiest way to do this is to just have it automatically loaded by putting the class in a package that's configured with the Extension.Packages parameter (see Extensions). Alternatively, you can configure the DefaultTagErrorRendererFactory to use the new renderer by using this init-param:

<init-param> 
    <param-name>TagErrorRenderer.Class</param-name> 
    <param-value>com.myco.web.util.CustomTagErrorRenderer</param-value> 
</init-param> 

For more details on configuration see the Runtime Configuration section in the Configuration Reference