Dashboard > Stripes 1.2 > ... > How To's > Display Errors
Stripes 1.2 Log In   View a printable version of the current page.
Display Errors
Added by Tim Fennell, last edited by Tim Fennell on Oct 10, 2005  (view change)

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 erorrs 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 override the default format to make it work better for single field output.

Example 3: Outputting errors by field
<stripes:form action="/foo/fist.action">
<table>
  <tr>
    <td>Username:</td>
    <td>
      <stripes:text name="username"/>
      <stripes:errors field="username">
          <stripes:individual-error/><br/>
      </stripes:errors>
    </td>
  </tr>
  <tr>
    <td>Username:</td>
    <td>
      <stripes:text name="password"/>
      <stripes:errors field="password">
          <stripes:individual-error/><br/>
      </stripes:errors>
    </td>
  </tr>

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 always returns an instance of DefaultTagErrorRenderer.

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 , 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.

"CustomTagErrorRenderer.java"
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. To do this requires writing your own TagErrorRendererFactory - but don't worry, it's trivial:

CustomTagErrorRendererFactory.java
public class CustomTagErrorRendererFactory implements TagErrorRendererFactory {

    public void init(Configuration configuration) throws Exception {
        // Doesn't do anything.  Doesn't even need to store config.
    }

    /**
     * Always returns an initialized instance of DefaultTagErrorRenderer.
     */
    public TagErrorRenderer getTagErrorRenderer(InputTagSupport tag) {
        TagErrorRenderer renderer = new CustomTagErrorRenderer();
        renderer.init(tag);
        return renderer;
    }
}

And then lastly, you'll need to wire in your custom factory. This is usually done through a initialization parameter for the Stripes Filter, in the web.xml. For example:

Configuring a custom factory
<init-param>
    <param-name>TagErrorRendererFactory.Class</param-name>
    <param-value>com.myco.myapp.web.CustomTagErrorRendererFactory</param-value>
</init-param>

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

Site powered by a free Open Source Project / Non-profit License (more) of Confluence - the Enterprise wiki.
Learn more or evaluate Confluence for your organisation.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.2.7 Build:#524 Jul 28, 2006) - Bug/feature request - Contact Administrators