Web application post-submit messages

09 January 2006

Peter Hilton

by Peter Hilton

What’s the right way to do confirmation messages in a web application after the user has done a database insert or update - like 'Customer details updated' after a permanent change? This article describes on approach that works well with Struts.

post submit

Example post-submit message

Struts messages

Struts lets you create and save these kinds of messages in the Action class with:

ActionMessages messages = new ActionMessages();
messages.add(Globals.MESSAGE_KEY, new ActionMessage("message.success"));
addMessages(request, messages);

You can then display the list of messages in the JSP with:

<html:messages message="true" id="message">
<bean:write name="message"/>

However, there's a problem with this in Struts 1.1.

The redirection problem

After doing something like an insert/update/delete in an Action, I normally send the user a redirect to a view page using something like:

ActionForward forward = new ActionForward("/customer/view?id=42");
return forward;

so that the current URL (i.e. browser history list entry) is no longer /customer/update. This is so that refreshing the page will not submit the form again and repeat the insert/update/delete.

The problem is that the Struts 1.1 messages mechanism relies on setting the messages in the request attribute, but sending a redirect creates a new request so there will be no messages.

The HttpSession solution

Fortunately, Struts 1.2 allows you to put the messages in the HttpSession. In your Action, do:

ActionMessages messages = new ActionMessages();
messages.add(Globals.MESSAGE_KEY, new ActionMessage("info.success"));

// Use the HttpSession instead of doing addMessages(request, messages);
request.getSession().setAttribute(Globals.MESSAGE_KEY, messages);

and in the JSP

<html:messages message="true" id="message">
<bean:write name="message"/>

It turns out that in Struts 1.2:

  1. <html:messages> also looks in the session scope, and if messages="true" it looks under the attribute name < %= org.apache.struts.Globals.MESSAGE_KEY %>. This is actually in the Struts documentation, but that only made sense after I had worked out what you are supposed to do.
  2. <html:messages> removes the messages from the session bean after it has displayed them, so you do not need to manually do:

    <% session.removeAttribute(org.apache.struts.Globals.MESSAGE_KEY); %>
  3. <html:messages> also has a name attribute that allows you to specify a session attribute name other than org.apache.struts.Globals.MESSAGE_KEY

Anyway, this means that if you have the JSP on every page (i.e. in the template) then you can put info messages in the HttpSession and know that they will be shown to the user precisely once.

Note that in practice the <html:messages> start tag is really something like

<html:messages message="true" id="message" header="info.header" footer="info.footer">

with the header and footer defined in the application resources

info.header = <ul class="donemessage">
info.footer = </ul>

This means that you could have separate message lists in the HttpSession and display separate lists for user info/done/warning/error messages, as on Tigris Style, whose stylesheet and icon is used in the example at the start of this article.