I'm currently migrating a Spring application from the JBoss J2EE container to Sun's Glassfish J2EE container and although it is the same code, I am getting a confusing error during a specific point in my application. The error occurs every time my controller redirects (using the redirect keyword) to a page handled by spring web flow. I've edited the jsp that should be rendered so that it is simply test text (and therefore I can't imagine my error is coming from JSP compilation). I've posted the stack trace pulled from my server log below. Due to the fact that none of my own classes are in the stack trace at all I'm not sure what other information would be useful for me to post. I should mention that I do not get this error at all in JBoss
[#|2010-01-15T14:59:06.334-0500|SEVERE|sun-appserver2.1|javax.enterprise.system.container.web|_ThreadID=18;_ThreadName=httpSSLWorkerThread-8080-3;_RequestID=ee69c2b0-30df-437f-ab22-fd8777dbf826;|StandardWrapperValve[burq]: PWC1406: Servlet.service() for servlet burq threw exception
java.lang.NullPointerException
at org.apache.jsp.WEB_002dINF.jsp.exception_jsp._jspService(exception_jsp.java:33)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:109)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:389)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:486)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:380)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:427)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:333)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at com.sun.identity.agents.filter.AmAgentBaseFilter.allowRequestToContinue(AmAgentBaseFilter.java:126)
at com.sun.identity.agents.filter.AmAgentBaseFilter.doFilter(AmAgentBaseFilter.java:75)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:246)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:873)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:723)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:558)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:490)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:382)
at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:240)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:252)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1173)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:901)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:809)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:427)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:333)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at com.sun.identity.agents.filter.AmAgentBaseFilter.allowRequestToContinue(AmAgentBaseFilter.java:126)
at com.sun.identity.agents.filter.AmAgentBaseFilter.doFilter(AmAgentBaseFilter.java:75)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:246)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:313)
at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:287)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:218)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:98)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:222)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:587)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1096)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:166)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:587)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1096)
at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:288)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:647)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:579)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:831)
at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341)
at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:263)
at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:214)
at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)
|#]
It appears the error is coming from the following call in the generated exception_jsp.java file:
response.setStatus(((Integer)request.getAttribute("javax.servlet.error.status_code")).intValue());
Here is the full exception_jsp.java file that is causing the null pointer:
package org.apache.jsp.WEB_002dINF.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.Transport;
import java.util.Properties;
import org.apache.commons.lang.exception.ExceptionUtils;
public final class exception_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();
private static java.util.Vector _jspx_dependants;
private org.apache.jasper.runtime.ResourceInjector _jspx_resourceInjector;
public Object getDependants() {
return _jspx_dependants;
}
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException {
PageContext pageContext = null;
HttpSession session = null;
Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request);
response.setStatus(((Integer)request.getAttribute("javax.servlet.error.status_code")).intValue());
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;
try {
response.setContentType("text/html");
response.setHeader("X-Powered-By", "JSP/2.1");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
_jspx_resourceInjector = (org.apache.jasper.runtime.ResourceInjector) application.getAttribute("com.sun.appserv.jsp.resource.injector");
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
out.write("\r\开发者_开发问答n");
out.write("<html lang=\"en\">\r\n");
out.write("\r\n");
out.write("\t<head>\r\n");
out.write("\t\t<link rel=\"stylesheet\" type=\"text/css\" href=\"/j2ee/shared/css/common.css\" />\r\n");
out.write("\t\t<script type=\"text/javascript\" language=\"javascript\" src=\"/j2ee/shared/js/base.js\"></script>\r\n");
out.write("\t</head>\t\t\r\n");
out.write("\t\r\n");
out.write("\t<body>\r\n");
out.write("\t\t<h1 title=\"BSS Update Retrieval and Query System 1.0.0\">BSS Update Retrieval and Query System</h1>\r\n");
out.write("\t\t\t\r\n");
out.write("\t ");
try {
Throwable ex = exception;
if(ex == null){
ex = ((Exception) request.getAttribute("exception"));
}
out.println("<p class='exception'>");
out.println("An error occured while running the BSS Update Request and Query system:- " + "<br/>");
out.println(ex.getMessage() + "<br/>");
out.println("Please contact " +"<a href='mailto:seqsupport@fstrf.org'>Sequencing Support</a>" + " for help.");
out.println("</p>");
out.println("<br><div style='display:none'>" + ExceptionUtils.getFullStackTrace(ex) + "</div><br/>");
Message message = new MimeMessage(Session.getInstance(new Properties()));
message.addRecipients(Message.RecipientType.TO, InternetAddress.parse("seqsupport@fstrf.org,seqdev@fstrf.org"));
message.addFrom(InternetAddress.parse("fstrf.labdivprgmng@fstrf.org"));
message.setSubject("Error - BSS Update Request and Query system");
StringBuffer content = new StringBuffer();
content.append("An exception occured while running the BSS Update Request and Query system: " + "\n");
content.append(ExceptionUtils.getFullStackTrace(ex));
message.setText(content.toString());
Transport.send(message);
}
catch(Exception e){
out.println(e.getMessage());
}
out.write("\r\n");
out.write("\t</body>\t\t\t\t\r\n");
out.write("</html>\r\n");
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
} catch (Throwable t) {
if (!(t instanceof SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
out.clearBuffer();
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
With GlassFish, the line:
response.setStatus(((Integer)request.getAttribute("javax.servlet.error.status_code")).intValue());
is automatically generated by the JSP compiler for any JSP that has:
<%@page isErrorPage="true"%>
Here, for an unknown reason, the "javax.servlet.error.status_code"
request attribute is not set or lost during the redirect so using <%@page isErrorPage="true"%>
results in the NPE. This may be a bug in your code, in GlassFish, or in Sping (or not at all), but it is impossible to say without more details on your page flow, on your code.
There is a discussion in this thread about a very similar problem (similar, not identical, the root cause is not the same IMO) though. The suggested workaround is to not use the isErrorPage
directive and to use the following EL code to access the error information:
${pageContext.errorData.throwable}
${pageContext.errorData.statusCode}
${pageContext.errorData.requestURI}
${pageContext.errorData.servletName}
As I said, I can't say if this is a bug in GlassFish, in Spring, or not a bug at all. But maybe open a ticket in GlassFish issue tracking system anyway. You may get a more precise answer (and help the community).
response.setStatus(((Integer)request.getAttribute("javax.servlet.error.status_code")).intValue());
this line is causing the problem. comment it out and try outputting the value of
request.getAttribute("javax.servlet.error.status_code")
(without casting or intValue()
)
It is perhaps null
javax.servlet.error.status_code
is only set if there has been an error. So if you are redirecting to the exception.jsp
yourself, and not using it as an error-page, then there is no status code set, and hence - the NullPointerException
Is that jsp page set as error page?
<web-app>
<!-- ..... -->
<error-page>
<error-code>
404
</error-code>
<location>
/404.html
</location>
</error-page>
<error-page>
<exception-type>
javax.servlet.ServletException
</exception-type>
<location>
/servlet/ErrorDisplay
</location>
</error-page>
<!-- ..... -->
A servlet in the for an rule could receive the following three attributes:
* javax.servlet.error.status_code : An Integer telling the error status code, if any
* javax.servlet.error.exception_type : A Class instance indicating the type of exception that caused the error, if any
* javax.servlet.error.message : A String telling the exception message, passed to the exception constructor
精彩评论