· software-development

HTML encoding/escaping with StringTemplate and Spring MVC

Last week my colleague T.C. and I had to work out how to HTML encode the values entered by the user when redisplaying those onto the page to prevent a cross site scripting attack on the website.

I wrote a blog post a couple of years ago describing how to do this in ASP.NET MVC and the general idea is that we need to have a custom renderer which HTML encodes any strings that pass through it.

In our case this means that we needed to write a custom renderer for String Template and hook that into Spring MVC.

We already had a view class StringTemplateView so we needed to add to that class and add our custom renderer.

The viewResolver was defined like so:

    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        return viewResolver;

And after some guidance from Jim we changed StringTemplateView to look like this:

public class StringTemplateView extends InternalResourceView {

    protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        String templateRootDir = format("%s/WEB-INF/templates", getServletContext().getRealPath("/"));

        StringTemplateGroup group = new StringTemplateGroup("view", templateRootDir);
        StringTemplate template = group.getInstanceOf(getBeanName());

        AttributeRenderer htmlEncodedRenderer = new HtmlEncodedRenderer();
        template.registerRenderer(String.class,  htmlEncodedRenderer);


    private class HtmlEncodedRenderer implements AttributeRenderer {
        public String toString(Object o) {
            return HtmlUtils.htmlEscape(o.toString());

        public String toString(Object o, String formatName) {
            return HtmlUtils.htmlEscape(o.toString());

At the moment we want to HTML encode everything that we render through StringTemplate but if that changes then we could make use of the formatName parameter which we’re currently ignoring.

In retrospect this looks pretty simple to do but my Googling skills were pretty much failing me at the time so I thought it’d be good to document.

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket