How to Improve Tapestry Errors Reporting When Using Bootstrap

Twitter recently released the Bootstrap framework. As I’m currently working on a recent project, I decided to give it a try on the Tapestry webapp.

So far, it proved to be easy to integrate. I introduced a Border component like this one:

package com.kalixia.iot.console.components;

import org.apache.tapestry5.annotations.Parameter;

public class Border {
    @Parameter(required = true, defaultPrefix = "literal")
    private String title;

    public String getTitle() {
        return title;

    public void setTitle(String title) {
        this.title = title;
<!DOCTYPE html>
<html lang="en" xmlns:t="">
    <meta charset="utf-8"/>
    <title>My Website :: ${title}</title>
    <meta name="description" content="My Website :: ${title}"/>
    <!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
    <!--[if lt IE 9]>
    <script src=""></script>
    <link rel="stylesheet" href=""/>
    <link rel="shortcut icon" href="images/favicon.ico">
    <link rel="apple-touch-icon" href="images/apple-touch-icon.png">
    <link rel="apple-touch-icon" sizes="72x72" href="images/apple-touch-icon-72x72.png">
    <link rel="apple-touch-icon" sizes="114x114" href="images/apple-touch-icon-114x114.png">



Unfortunately, error messages where not displayed in a nice way. The end result was an ugly error message. After going through Bootstrap demo page, I was able to find out the required markup to add when displaying an error. The next part was to find out how to tweak Tapestry in such a way that it would render the errors using Bootstrap.

I found out that we are supposed to override the default ValidationDecorator. The easy way to do this is within your Module class:

public static void contributeMarkupRenderer(OrderedConfiguration<MarkupRendererFilter> configuration,
                                            final Environment environment) {
    MarkupRendererFilter validationDecorator = new MarkupRendererFilter() {
        public void renderMarkup(MarkupWriter writer, MarkupRenderer renderer) {
            ValidationDecorator decorator = new BootstrapValidationDecorator(environment, writer);
            environment.push(ValidationDecorator.class, decorator);
    configuration.override("DefaultValidationDecorator", validationDecorator);

You then need to add the following class which does all the required markup stuff:

 * Override default Tapestry validation decorator, so that CSS class of the "row"
 * is added an "error" CSS class if the field is in error.
 * @author Jerome Bernard
public class BootstrapValidationDecorator extends BaseValidationDecorator {
    private final Environment environment;
    private final MarkupWriter markupWriter;

     * @param environment  used to locate objects and services during the render
     * @param markupWriter
    public BootstrapValidationDecorator(Environment environment, MarkupWriter markupWriter) {
        this.environment = environment;
        this.markupWriter = markupWriter;

    public void insideField(Field field) {
        if (inError(field))

    public void afterField(Field field) {
        if (inError(field)) {
            markupWriter.element("span", "class", "help-inline");

    private void addErrorClassToUpperDivElement() {
        Element element = markupWriter.getElement();
        do {
            element = element.getContainer();
        } while (!element.getAttribute("class").contains("clearfix"));

    private boolean inError(Field field) {
        ValidationTracker tracker = environment.peekRequired(ValidationTracker.class);
        return tracker.inError(field);

    private String getErrorMessage(Field field) {
        ValidationTracker tracker = environment.peekRequired(ValidationTracker.class);
        return tracker.getError(field);

Displaying an error for a form field is way nicer now: Screenshot from a sample form

comments powered by Disqus