web-dev-qa-db-ja.com

ジャージー:無効なリクエスト本文が指定された場合、500ではなく400エラーを返す

ジャージーの統合されたJackson処理を使用して、着信JSONをPOJOに変換しています。例:

@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response newCustomer( CustomerRepresentation customer)
{
...
}

クライアントが無効なフィールドでJSONを送信した場合、Jerseyは現在500 Internal Server Errorを返します。代わりに、400 Bad Requestを返したいのですが、エラーのあるフィールドを示す意味のある詳細が望ましいです。

これをどのように達成できるかについての洞察はありますか? (少なくとも、完全に不適切な500ではなく一般的な400を返しますか?)

更新:ハンドラーが呼び出される前にサーバー側で生成される例外は次のとおりです。

javax.servlet.ServletException: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: 
Unrecognized field "this_isnt_a_known"_field" (Class com.redacted....), not marked as ignorable
21
HolySamosa

ExceptionMapperを実装してJacksonによってスローされたUnrecognizedPropertyExceptionをキャッチし、それを400 Bad Request応答にマップすることで、最終的にこの問題を回避することができました。

@Provider
public class UnrecognizedPropertyExceptionMapper implements ExceptionMapper<UnrecognizedPropertyException>
{

    @Override
    public Response toResponse(UnrecognizedPropertyException exception)
    {
        return Response
                .status(Response.Status.BAD_REQUEST)
                .entity( "'" + exception.getUnrecognizedPropertyName() + "' is an unrecognized field.")
                .type( MediaType.TEXT_PLAIN)
                .build();
    }

}
19
HolySamosa

ドロップウィザードの土地には、 JsonProcessingExceptionMapper と呼ばれるExceptionMapperがあり、探しているものと同様の機能を備えています。ドロップウィザード以外の世界で特定の問題に対処する方法についてのインスピレーションを得るために、それを使用できるかもしれません。

3
Trevor Mack

HolySamosaの回答でstatus 5status 4にマッピングしようとしましたが、このマッパーで例外がキャッチされず、status 5がまだ返されていました。

デバッグ後、JsonParseExceptionがスローされ、nrecognizedPropertyExceptionではないことがわかりました。これは、ガベージテキスト(JSONではない)を送信していたためです。

サーバー側のDTOに適さない形式で、クライアント側から適切なJSONを送信すると、nrecognizedPropertyExceptionが発生しました。したがって、これには2つのケースがあります。

  • jSONではないガベージを送信するとき
  • jSONを送信するが、DTOクラスと一致しない場合。

今私は両方のためにステータス4を返しています。

3
jovankricka

私はこれと同じ問題を抱えています...残念ながら、ジャクソンの例外をインターセプトして独自のエラーコードを生成するための良い方法はありません。

必要なオプションの1つは、@JsonIgnorePropertiesを使用してから、逆シリアル化されたオブジェクトを厳密に検証することです。これは、送信者がジャンクを送信したかどうかはわかりませんが、必須フィールドを見逃した場合は、それをキャッチします。

渡された実際のJSONにアクセスする方法を見つけることができません。ただし、@ Providerクラスを作成して、JSONをトラップし、検証してから、逆シリアル化のためにJacksonに渡します。

1
JasonB