これまでに出会ったExceptionHandlerFactory
の例はすべて、ViewExpiredException
が検出された場合にユーザーをviewExpired.jsf
ページにリダイレクトします。
public class ViewExpiredExceptionExceptionHandler extends ExceptionHandlerWrapper {
private ExceptionHandler wrapped;
public ViewExpiredExceptionExceptionHandler(ExceptionHandler wrapped) {
this.wrapped = wrapped;
}
@Override
public ExceptionHandler getWrapped() {
return this.wrapped;
}
@Override
public void handle() throws FacesException {
for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();) {
ExceptionQueuedEvent event = i.next();
ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
Throwable t = context.getException();
if (t instanceof ViewExpiredException) {
ViewExpiredException vee = (ViewExpiredException) t;
FacesContext facesContext = FacesContext.getCurrentInstance();
Map<String, Object> requestMap = facesContext.getExternalContext().getRequestMap();
NavigationHandler navigationHandler = facesContext.getApplication().getNavigationHandler();
try {
// Push some useful stuff to the request scope for use in the page
requestMap.put("currentViewId", vee.getViewId());
navigationHandler.handleNavigation(facesContext, null, "/viewExpired");
facesContext.renderResponse();
} finally {
i.remove();
}
}
}
// At this point, the queue will not contain any ViewExpiredEvents. Therefore, let the parent handle them.
getWrapped().handle();
}
}
次の単純なweb.xml
構成は基本的に同じで、はるかに単純なようです。
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/viewExpired.jsf</location>
</error-page>
これは質問を促します-なぜExceptionHandlerFactory
を使うのですか?
特定の例は、1つの有用なことだけを実行します。たとえば、次のように使用できるように、ビューIDを要求属性として保存します。
<h:link value="Go back to previous page" outcome="#{currentViewId}" />
ただし、生のリクエストURIは<error-page>
のデフォルトのリクエスト属性javax.servlet.error.request_uri
ですでに利用可能であるため、これはそれほど有用ではありません。
<h:outputLink value="#{requestScope['javax.servlet.error.request_uri']}">Go back to previous page</h:outputLink>
ただし、カスタムExceptionHandler
が実際に役立つのは、ajax要求中の例外を処理できることです。つまり、デフォルトでは、クライアント側に役立つフィードバックの単一の形式はありません。プロジェクトステージが「開発」に設定されているMojarraでのみ、例外メッセージを含む裸のJavaScript警告メッセージが表示されます。しかし、それだけです。 「制作」段階では、単一のフィードバック形式はありません。カスタムExceptionHandler
を使用すると、web.xml
を解析してエラーページの場所を見つけ、それを使用して新しいUIViewRoot
を作成し、JSFにajaxレンダリングを@all
に設定することができます。
したがって、基本的に:
String errorPageLocation = "/WEB-INF/errorpages/500.xhtml";
context.setViewRoot(context.getApplication().getViewHandler().createView(context, errorPageLocation));
context.getPartialViewContext().setRenderAll(true);
context.renderResponse();
この関連する質問も参照してください: AJAX化されたコンポーネントのJSF 2.0例外を処理する正しい方法は何ですか? およびこのブログ: Full Ajax Exception Handler 。
ViewExpiredException
を受け取ったときに何をしたいかによって異なります。
ユーザーエラーページを表示したいだけなら、あなたが言ったようにそれを行うことができます。
これは post がプログラムでViewExpiredException
をインターセプトし、それを使って何か素敵なことをする方法を示しています。