50.4. 例外の応答へのマッピング
概要 リンクのコピーリンクがクリップボードにコピーされました!
WebApplicationException 例外の出力が現実的でない場合や、不可能な場合があります。たとえば、可能な例外をすべてキャッチし、そのような例外に対して WebApplicationException を作成する必要がない場合があります。また、アプリケーションコードの操作を容易にするカスタムの例外を使用することもできます。
このようなケースを処理するために、JAX-RS API では、クライアントに送信する Response オブジェクトを生成するカスタム例外プロバイダーを実装できます。カスタム例外プロバイダーは、ExceptionMapper<E> インターフェイスを実装して作成されます。Apache CXF ランタイムで登録されると、型 E の例外が出力されるたびにカスタムプロバイダーが使用されます。
例外マッパーの選択方法 リンクのコピーリンクがクリップボードにコピーされました!
例外マッパーは 2 つのケースで使用されます。
- 例外またはそのサブクラスの 1 つが出力されると、ランタイムは適切な例外マッパーをチェックします。特定の例外出力を処理する場合は、例外マッパーが選択されます。出力された特定の例外の例外マッパーがない場合には、例外の中で最も近いスーパークラスの例外マッパーが選択されます。
デフォルトでは、WebApplicationException はデフォルトマッパー
WebApplicationExceptionMapperによって処理されます。WebApplicationException 例外を処理する可能性がある追加のカスタムマッパーが登録されていても (カスタムRuntimeExceptionマッパーなど)、カスタムマッパーは 使用されず、代わりにWebApplicationExceptionMapperが使用されます。ただし、この動作は
Messageオブジェクトのdefault.wae.mapper.least.specificプロパティーをtrueに設定して変更できます。このオプションを有効にすると、カスタム例外マッパーを使用して WebApplicationException 例外を処理できるようにするため、デフォルトのWebApplicationExceptionMapperの優先順位は最低になります。たとえば、このオプションが有効な場合に、カスタムRuntimeExceptionマッパーを登録することで WebApplicationException 例外をキャッチできます。「WebApplicationException の例外マッパーの登録」を参照してください。
例外に、例外マッパーがない場合には、この例外は ServletException 例外でラップされ、コンテナーランタイムに渡されます。その後、コンテナーランタイムは例外の処理方法を決定します。
例外マッパーの実装 リンクのコピーリンクがクリップボードにコピーされました!
例外マッパーは、javax.ws.rs.ext.ExceptionMapper<E> インターフェイスを実装して作成されます。例50.5「例外マッパーのインターフェイス」で示されているように、インターフェイスには単一のメソッド toResponse() があります。これは元の例外をパラメーターとして取り、Response オブジェクトを返します。
例50.5 例外マッパーのインターフェイス
public interface ExceptionMapper<E extends java.lang.Throwable>
{
public Response toResponse(E exception);
}
public interface ExceptionMapper<E extends java.lang.Throwable>
{
public Response toResponse(E exception);
}
例外マッパーによって作成された Response オブジェクトは、他の Response オブジェクトのようにランタイムによって処理されます。コンシューマーへの結果となる応答には、Response オブジェクトにカプセル化されたステータス、ヘッダー、およびエンティティーボディーが含まれます。
例外マッパー実装はランタイムによってプロバイダーとみなされます。そのため、@Provider アノテーションを付ける必要があります。
例外マッパーによる Response オブジェクトの構築中に例外が発生すると、ランタイムは 500 Server Error のステータスで応答をコンシューマーに送信します。
例50.6「例外の応答へのマッピング」は、Spring AccessDeniedException 例外を遮断し、 403 Forbidden ステータスと空のエンティティーボディーで応答を生成する例外マッパーを示しています。
例50.6 例外の応答へのマッピング
ランタイムは AccessDeniedException 例外をキャッチし、空のエンティティーボディーと 403 のステータスで Response オブジェクトを作成します。ランタイムは、通常のレスポンスの場合と同様に Response オブジェクトを処理します。その結果、コンシューマーはステータスが 403 の HTTP 応答を受信します。
例外マッパーの登録 リンクのコピーリンクがクリップボードにコピーされました!
JAX-RS アプリケーションが例外マッパーを使用する前に、例外マッパーをランタイムに登録する必要があります。例外マッパーは、アプリケーションの設定ファイルの jaxrs:providers 要素を使用してランタイムで登録されます。
jaxrs:providers 要素は jaxrs:server 要素の子で、bean 要素のリストが含まれます。各 bean 要素は 1 つの例外マッパーを定義します。
例50.7「ランタイムへの例外マッパーの登録」は、カスタム例外マッパー SecurityExceptionMapper を使用するように設定された JAX-RS サーバーを示しています。
例50.7 ランタイムへの例外マッパーの登録
WebApplicationException の例外マッパーの登録 リンクのコピーリンクがクリップボードにコピーされました!
WebApplicationException 例外の例外マッパーを登録することは、この例外型はデフォルトの WebApplicationExceptionMapper によって自動的に処理されるため、特殊なケースです。通常、WebApplicationException を処理する予定のカスタムマッパーを登録する場合でも、引き続きデフォルトの WebApplicationExceptionMapper によって処理されます。このデフォルトの動作を変更するには、default.wae.mapper.least.specific プロパティーを true に設定する必要があります。
たとえば、以下の XML コードは JAX-RS エンドポイントで default.wae.mapper.least.specific プロパティーを有効にする方法を示しています。
以下の例のように、インターセプターで default.wae.mapper.least.specific プロパティーを設定することもできます。
// Java
public void handleMessage(Message message)
{
m.put("default.wae.mapper.least.specific", true);
...
// Java
public void handleMessage(Message message)
{
m.put("default.wae.mapper.least.specific", true);
...