7

Jetty/RESTEasyアプリに取り組んでいます。RESTエンドポイントの1つからをスローするWebApplicationException(myResponse)と、指定された応答がクライアントに送信されます。

フィルタがエラーを検出したとき、私は同じ振る舞いをしたいです:

  1. 実行の続行を停止する必要があり、
  2. スタックトレースを含まない、明確なJSON形式のエラーをユーザーに提供する必要があります。

明らかに、応答ストリームに書き込んでreturningするだけで、doFilterメソッド内から機能します。ただし、これはによって呼び出される他のメソッドでは機能しませんdoFilter

例外をスローすると条件#1が満たされますが、条件#2を満たすための適切な方法がわかりません。(一番下に私の最善の試みを見ることができます。)

Perceptionが彼の回答で説明したように、WebApplicationExceptionsはフィルターのコンテキストでは他の例外と同様に扱われるため、ユーザーに見苦しいスタックトレースを提供します。

だから、私の質問を要約すると:

  • サーブレットコンテナには同等のものがありthrow new WebApplicationException(Response)ますか?
  • そしておそらくもっと重要なのは、他のJavaプロジェクトがこれをどのように処理するのでしょうか。

私はこのコードを1つのフィルターに入れて動作しますが、すべてのフィルターに自動的に適用されるより洗練されたソリューションを好みます。

public void doFilter(final ServletRequest   request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
    try {
        doFilterOrThrow(request, response, chain);
    } catch (WebApplicationException e) {
        Response res = e.getResponse();
        ((HttpServletResponse) response).sendError(res.getStatus(), (String) res.getEntity());
    }
}
4

1 に答える 1

7

Webアプリケーションの例外について言及した特定の処理は、JAX-RSコンテナのコンテキスト内でのみ定義されます。これは、サーブレットコンテナと同じものではありません。

Webフィルタは、サーブレットコンテナによって処理されます。サーブレットコンテナは、JAX-RSコンテナが同じアプリケーションサーバー内に存在することを認識または認識しません。また、Webアプリケーションの例外を認識または気にしません。したがって、フィルター内からWAEをスローすると、他の例外とまったく同じように扱われます(スタックトレースを使用したサーバーエラー、またはWebアプリケーションで設定した場合は事前構成されたエラーページ)。

クライアントにエラーを示している場合は、応答ストリームに直接書き込むことで、フィルターから簡単にそれを行うことができるように思われます。ただし、既存のJAX-RSロジックを活用しようとしている場合、(RESTEasy固有の)ソリューションは、フィルターでエラーとしてリクエストにフラグを立て、プロバイダークラスを使用してJAX-RSでWAEを生成することです。例:

@WebFilter(urlPatterns = "*")
public class ForwardingFilter implements Filter {

    @Override
    public void destroy() {
        return;
    }

    @Override
    public void doFilter(final ServletRequest request,
            final ServletResponse response, final FilterChain chain)
            throws IOException, ServletException {
        // Add an error response to be processed by the JAX-RS container.
        // This would obviously be based on some condition.
        request.setAttribute("errorResponse",
                Response.status(500).entity("Didn't work out!").build());
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        return;
    }
}

@Provider
@ServerInterceptor
@HeaderDecoratorPrecedence
@RequestScoped
public class ForwardingHandlerProvider implements PreProcessInterceptor {

    @Override
    public ServerResponse preProcess(final HttpRequest request,
            final ResourceMethod method) throws Failure,
            WebApplicationException {
        final Response errorResponse = (Response) request
                .getAttribute("errorResponse");
        if (errorResponse != null)
            throw new WebApplicationException(errorResponse);
        return null;
    }
}

プロバイダーはJAX-RSランドに存在するため、Webアプリケーションの例外はJAX-RS仕様のセクション3.3.4のルールに従って処理され、クライアント側で目的の応答を取得します。

* 編集:*

要するに、JAX-RSで利用可能なものと同様に、サーブレットの例外を一元的に処理するための標準のJava EE規定の方法は(現在)ありません。ただし、JBoss / RestEASYを使用しているので、JBossSeamCatchライブラリを利用してかなり近づけることができます

@HandlesExceptions
public class ExceptionHandler {
    public void handleServletException(
            final @Handles @WebRequest CaughtException<ServletException> caught,
            @Context final HttpServletResponse response) {
        try {
            response.sendError(500, "An error occured");
        } catch (final IOException ioe) {
            System.err.println("Dumb IO Exception: " + ioe);
        }
    }
}

上記は、SeamCatchのドキュメントで説明されている例外ハンドラーを示しています。現在、ライブラリは非常に流動的であるため、最後の手段としてのみ利用することをお勧めします。

于 2013-05-13T17:12:19.077 に答える