HTTP 500 でエラーが発生した場合に、意味のある応答をユーザーに確実に提供したい JSF アプリがあります。 OutOfMemoryError を強制するとアプリが停止しますが、Tomcat 6.0.35 からデフォルトの 500 エラーページが表示されます。
私のアプリ設定の関連部分は次のとおりです。
web.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 に対する答えが「はい」の場合、実装の最も効率的な方法は何ですか (できれば最大限の知識を得るためにコード スニップを使用します)。
ありがとう