Debugging Java web based applications is often a slow and tedious task, since we need to keep looking for error messages in the log files. This article demonstrates a technique to direct stacktraces caused by Java exceptions to the browser, potentially saving us a lot of time.
Those of us that have been writing Java web applications since before
JSPs existed may fondly (or not so fondly) remember how those
applications used to be written in the "good old days". Basically, to
generate HTML output, a developer had to embed HTML code into a String
,
and pass that String
to as a parameter to the javax.servlet.ServletOutputStream.print()
class. This practice led to the creation of lots of hard to maintain
applications, which in turn encouraged Sun to develop the JSP
specification, but I digress. If we can find a way to pass a stack trace
as a parameter to this method, then we can achieve our goal and be able
to debug our applications a lot faster.
Looking at the API for ServletOutputStream
, there is no
method we can use to directly output the stack trace to the browser.
Going the other way, looking at the java.lang.Exception
class, there is no method to be found that would send the stack trace to
a String
object. What do we do?
Upon further examination of the Exception
class, we can
see that we can send the output of the printStackTrace()
method to a java.io.PrintWriter
object. We know we can use
a PrintWriter
to populate a java.io.StringWriter
object by passing the latter as a parameter to the former's constructor.
We also know that the toString
method of StringWriter
will return a plain old String
with its contents. Putting
all this knowledge together, we can come up with a way to display a
stack trace in the browser.
package net.ensode.buggyservlet;
//imports obviated
public class BuggyServlet extends HttpServlet
{
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
Object nullObject = null;
try
{
nullObject.toString(); //force an exception
}
catch (Exception e)
{
// display stack trace in the browser
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
e.printStackTrace(printWriter);
response.setContentType("text/plain");
response.getOutputStream().print(stringWriter.toString());
}
}
}
After running this servlet, we are "greeted" with a stack trace on the browser. By using this technique our servlet debugging will go much faster from now on.