我有一个 JSF 应用程序,我想确保在它出现 HTTP 500 错误时为用户提供有意义的响应。当我强制执行 OutOfMemoryError 时,该应用程序会死掉,但我从 Tomcat 6.0.35 得到一个默认的 500 错误页面。
我的应用程序设置的相关部分是:
网页.xml:
<filter>
<filter-name>Error</filter-name>
<filter-class>myApp.ErrorFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Error</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/expiredIndex.jsf</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error.jsf</location>
</error-page>
错误过滤器.java:
public class ErrorFilter implements Filter {
static Logger logger = Logger.getLogger("MYAPP");
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
chain.doFilter(request, response);
} catch (ServletException e) {
logger.error(getDirID()+"|"+"Caught Servlet Exception");
Throwable rootCause = e.getRootCause();
logger.error(getDirID()+"|"+"Root cause is " + rootCause.toString());
if (rootCause instanceof RuntimeException) { // This is true for any FacesException.
logger.error(getDirID()+"|"+"Rethrowing exception as RuntimeException" + rootCause.toString());
throw (RuntimeException) rootCause; // Throw wrapped RuntimeException instead of ServletException.
} else {
throw e;
}
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
public String getDirID() {
DirID newDirID = new DirID();
String dirID = newDirID.getDirID();
return dirID;
}
}
减少堆栈跟踪为您的乐趣:
2012-09-17 17:35:51,881|ERROR|[http-8080-1]:Exception in the filter chain
javax.servlet.ServletException: Servlet execution threw an exception
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:313)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
...
Caused by: java.lang.OutOfMemoryError: Java heap space
at com.sun.facelets.util.FastWriter.overflow(FastWriter.java:50)
at com.sun.facelets.util.FastWriter.write(FastWriter.java:57)
...
Sep 17, 2012 5:35:51 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet Faces Servlet threw exception
java.lang.NullPointerException
at myApp.DirID.getDirID(DirID.java:27)
at myApp.ErrorFilter.getDirID(ErrorFilter.java:50)
at myApp.ErrorFilter.doFilter(ErrorFilter.java:31)
可能是最相关的位:
Sep 17, 2012 5:35:51 PM com.sun.faces.lifecycle.Phase doPhase
SEVERE: JSF1054: (Phase ID: RESTORE_VIEW 1, View ID: ) Exception thrown during phase execution: javax.faces.event.PhaseEvent[source=com.sun.faces.lifecycle.LifecycleImpl@16968dd]
Sep 17, 2012 5:35:51 PM org.apache.catalina.core.ApplicationDispatcher invoke
SEVERE: Servlet.service() for servlet Faces Servlet threw exception
javax.faces.application.ViewExpiredException: viewId:/error.jsf - View /error.jsf could not be restored.
现在我对此的看法是,容器在达到最大内存限制时会死掉,因此在堆栈所在的状态下无法访问 error.jsf posh 错误页面。
我的问题是:
- 鉴于原因是突然的内存不足错误,我可以从中恢复,以便服务器有足够的空间重定向到我的 error.jsf 页面吗?
- 如果对 1 的回答是肯定的,那么最有效的实现方法是什么(最好使用代码片段来获得最大的权威性)。
谢谢