Get the output of a jsp or servlet response as String

September 25th, 2011

Well, at the first glance the answer to this problem would be to just make an http request to the jsp file and get the output!

The problem

In fact, many libraries can help you do that and you also have java's HttpUrlConnection. This solution will work in most cases. At least it worked for me but I was never really happy with it. The jsp is within my webapp, why should I make an http connection to my webapp to get the computed output of the jsp? Not to mention that I had to pass all of my parameters again as my jsp could not use the attributes within my current request scope.

Thanks God, the HttpUrlConnection solution stopped working after changing the network topology of the webapp. So instead of trying to tweak this solution I just thought of the better one as at that point I had the knowledge I needed!

The goal

So, the goal is to have the web container generate the output and instead of writing to the servlet output, write it to "something else" I had access to. Cool, how to do that? After a little reading you can find out that the container writes the output of the jsp using the writer of HttpServletResponse.getWriter() just like you do when you want to directly write to the output of you response. That happens because after all the jsp's are translated into servlets, get compiled and used as plain servlets.

The solution

Applying some OO patterns, the problem seems strait forward. First of all we need a custom HttpServletResponse where we would provide our custom writer when someone uses the getWriter() method. As for the writer, we need one that we can the access in order to get it's content. Again java provides us with this tool and it's called CharArrayWriter. Finally we can use the HttpServletRequestWrapper to decorate our response!

import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

public class CharArrayWriterResponse extends HttpServletResponseWrapper {
	
  private final CharArrayWriter charArray = new CharArrayWriter();

  public CharArrayWriterResponse(HttpServletResponse response) {
    super(response);
  }

  @Override
  public PrintWriter getWriter() throws IOException {
    return new PrintWriter(charArray);
  }

  public String getOutput() {
    return charArray.toString();
  }
}

The wiring

Ok done! Now how do I use it? Well, let's say that you want to get the output of a jsp file in order to use it for the body of an html email (that was my case). Then you should wrap the actual HttpServletResponse with your's and let the servlet container use that one. There is a servlet that does exactly that:

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class ServletUsingCustomResponse extends HttpServlet {

  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String template = req.getParameter("tmpl");

    CharArrayWriterResponse customResponse  = new CharArrayWriterResponse(resp);
    req.getRequestDispatcher(template).forward(req, customResponse);

    System.out.println(String.format("The output of %s is %s", template, customResponse.getOutput()));
  }
}

valotas.com v3.13.1 © Georgios Valotasios - CSS inspired by Adam Wathan's blog