24

I have set my error page like this in web.xml:

 <error-page>
  <exception-type>java.lang.Exception</exception-type>
  <location>/errors/error.jsp</location>
 </error-page>

Now I would like to print stack trace of error on JSP (of course in development mode only). How can I print stack trace of error on my JSP page? I don't use any frameworks for this application, so only default servlet APIs are available for my program.

jmj
  • 232,312
  • 42
  • 391
  • 431
newbie
  • 23,730
  • 77
  • 197
  • 300

9 Answers9

23

get the parameter from request that is set internally and use it to print and deal with other information like cause, message

<c:set var="exception" value="${requestScope['javax.servlet.error.exception']}"/>

and to print stacktrace

<!-- Stack trace -->
<jsp:scriptlet>
  exception.printStackTrace(new java.io.PrintWriter(out));
</jsp:scriptlet>

See Also

jmj
  • 232,312
  • 42
  • 391
  • 431
21

The following parameters will be set by the container when request is forwarded to the error page.

  • javax.servlet.error.status_code
  • javax.servlet.error.exception
  • javax.servlet.error.message
  • javax.servlet.error.request_uri
  • javax.servlet.error.servlet_name
  • javax.servlet.error.exception_type

In your error JSP do this,

<%request.getAttribute("javax.servlet.error.exception").printStackTrace(new java.io.PrintWriter(out))%>;

Or Else If your error page is defined as Error page with Page Directive like,

<%@ page isErrorPage="true" import="java.io.*"%>

The exception scripting variable will be declared in the JSP. You can printing the scripting variable using a scriptlet using,

exception.printStackTrace(new java.io.PrintWriter(out));

Or,

<jsp:scriptlet>
    exception.printStackTrace(response.getWriter())
</jsp:scriptlet>
Unmitigated
  • 46,070
  • 7
  • 44
  • 60
Ramesh PVK
  • 15,050
  • 2
  • 44
  • 49
14

Using JSP scriptlets is a frowned upon practice since a decade. You'd best avoid it.

If you're already on EL 2.2 or newer (Tomcat 7+, JBoss AS 6+, WildFly, GlassFish 3+, etc), with new support for method expressions of the form ${instance.method()}, then you can just use 100% EL for this.

First you need to explicitly flush the JSP writer via JspWriter#flush(), so that all preceding JSP template output really gets written to the writer of the servlet response:

${pageContext.out.flush()}

Then you can just pass ServletResponse#getWriter() to Throwable#printStackTrace().

${exception.printStackTrace(pageContext.response.writer)}

Complete example:

<%@page pageEncoding="UTF-8" isErrorPage="true" %>
...
<pre>${pageContext.out.flush()}${exception.printStackTrace(pageContext.response.writer)}</pre>

If you're already on EL 3.0 (Tomcat 8+, WildFly, GlassFish 4+, etc), you can even make it a single expression with the new semicolon operator which separates EL statements:

<%@page pageEncoding="UTF-8" isErrorPage="true" %>
...
<pre>${pageContext.out.flush();exception.printStackTrace(pageContext.response.writer)}</pre>

If you can't use isErrorPage="true" for some reason (and thus ${exception} implicit object isn't available), then just substitute with ${requestScope['javax.servlet.error.exception']}:

<%@page pageEncoding="UTF-8" %>
...
<pre>${pageContext.out.flush()}${requestScope['javax.servlet.error.exception'].printStackTrace(pageContext.response.writer)}</pre>

If you're still not on EL 2.2, then your best bet is creating a custom EL function. Detail can be found in What is the good approach to forward the exception from servlets to a jsp page?

Below is a more complete error page example with more detail:

<%@page pageEncoding="UTF-8" isErrorPage="true" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
...
<ul>
    <li>Exception: <c:out value="${requestScope['javax.servlet.error.exception']}" /></li>
    <li>Exception type: <c:out value="${requestScope['javax.servlet.error.exception_type']}" /></li>
    <li>Exception message: <c:out value="${requestScope['javax.servlet.error.message']}" /></li>
    <li>Request URI: <c:out value="${requestScope['javax.servlet.error.request_uri']}" /></li>
    <li>Servlet name: <c:out value="${requestScope['javax.servlet.error.servlet_name']}" /></li>
    <li>Status code: <c:out value="${requestScope['javax.servlet.error.status_code']}" /></li>
    <li>Stack trace: <pre>${pageContext.out.flush()}${exception.printStackTrace(pageContext.response.writer)}</pre></li>
</ul>
Community
  • 1
  • 1
BalusC
  • 1,040,783
  • 362
  • 3,548
  • 3,513
  • One issue I have encountered is that sometimes the stack trace will contain lines of JSP. These are getting interpreted as HTML in the browser. Is there a means to escape the stack trace? (Normally I'd use c:out but that does not apply in this case.) – peater Aug 13 '19 at 19:13
5

May be it helps to you..
it will be show exception StackTrace into browser

exception.printStackTrace(response.getWriter());  

Or

<%
  try{
     int test = Integer.parseInt("hola");
  }catch(Exception e){
     **// HERE THE MAGIC BEGINS!!**
     out.println("<div id=\"error\">");
     e.printStackTrace(new java.io.PrintWriter(out));
    out.println("</div>");
    **// THE MAGIC ENDS!!**
  }
%>

If you declare <% page isErrorPage="true" %> in top of error.jsp, then you have access to the thrown Exception (and thus also all of its getters) by ${exception}

<p>Message: ${exception.message}  

see more.. Mapping Errors to Error Screens

Sumit Singh
  • 24,095
  • 8
  • 74
  • 100
3

Or, to avoid using scriptlets in your jsp, use jstl:

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
...

<c:set var="exception" value="${requestScope['javax.servlet.error.exception']}"/>

<c:if test="${exception != null}">
  <h4>${exception}</h4>
  <c:forEach var="stackTraceElem" items="${exception.stackTrace}">
    <c:out value="${stackTraceElem}"/><br/>
  </c:forEach>
</c:if>

Ideally, scriptlets should be disallowed as a best practice. Explicitly prevent scriplets in you jsp files via the web.xml configuration:

<jsp-config>
  <jsp-property-group>
    <url-pattern>*.jsp</url-pattern>
    <scripting-invalid>true</scripting-invalid>
  </jsp-property-group>
</jsp-config>
Brice Roncace
  • 9,401
  • 8
  • 58
  • 67
3

On the error page, just do:

<jsp:scriptlet>
    exception.printStackTrace(response.getWriter())
</jsp:scriptlet>

Although this begs the question: what is a user going to do with an exception. Why not write the exception to the error log so it is persisted and you can go back to it after a user complains?

Abimaran Kugathasan
  • 29,154
  • 11
  • 70
  • 102
2

Thrown Exception object is available as request attribute with name 'javax.servlet.error.exception'. So, in your JSP, you can write:

<% request.getAttribute("javax.servlet.error.exception").printStackTrace(new java.io.PrintWriter(out); %>
socha23
  • 9,971
  • 2
  • 27
  • 25
1

You can use jstl core library

1) Import tablib on top of JSP file

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

2) use tag

<c:catch var="myExceptionObject">
    Code that might throw Exception
</c:catch>

<c:if test="${myExceptionObject} != null">
    There was an exception: ${myExceptionObject.message}
</c:if>
peater
  • 1,193
  • 14
  • 18
0

In the error.jsp add the below lines

<%Logger log = Logger.getLogger("error_jsp.class");
Exception e = (Exception)request.getAttribute("javax.servlet.error.exception");
log.debug(request.getAttribute("javax.servlet.error.message"));
e.printStackTrace();
log.debug(e.getStackTrace());%>
Ragu14
  • 1
  • 1