web-dev-qa-db-ja.com

<error-page>リダイレクトの代わりにJSF ExceptionHandlerFactoryを使用する理由

これまでに出会った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を使うのですか?

26
8bitjunkie

特定の例は、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

26
BalusC

ViewExpiredExceptionを受け取ったときに何をしたいかによって異なります。

ユーザーエラーページを表示したいだけなら、あなたが言ったようにそれを行うことができます。

これは post がプログラムでViewExpiredExceptionをインターセプトし、それを使って何か素敵なことをする方法を示しています。

3
choop