3

POSTメソッドを介してオブジェクトをXMLとして受け入れるJerseyサービスがあります。予想どおり無効なデータ(フィールドが長すぎるなど)が原因で、マーシャリング中にエラーが発生することがあります。一般的な「クライアントから送信された要求が構文的に正しくありませんでした」というエラーを取得する代わりに、これらのエラーを適切にキャプチャして返すにはどうすればよいですか。

明確化: REST呼び出しの本体は次のようになります。

@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Path("/users")
@POST
public Response createUser(@Context SecurityContext sc, User user) {
    // do some stuff
}

ユーザーオブジェクトが呼び出しの本文として送信される場所。Userオブジェクトのセットでエラーが発生しています。

4

1 に答える 1

0

まず、メソッドの引数を String または Map のいずれかを取るように変更する必要があります。次に、マーシャリングを次のように制御できます。

@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Path("/users")
@POST
public Response createUser(@Context SecurityContext sc, String json ) {
    ObjectMapper mapper = new ObjectMapper();
    User user = mapper.readValue( json, User.class );

次に、この周りに try..catch を配置して、検証エラーをキャッチできます。これをクライアントに返す場合は、BAD_REQUEST の Response を作成してから、リクエストのエンティティのオブジェクトを作成します。ConstrainViolationExcpetion によく似たものを作成します。基本的に、1 行のメッセージの説明と、「フィールド」および「詳細」のフィールドを持つオブジェクトのコレクションがあります。次に、それを JSON または XML としてクライアントに返します。JSON での出力例を次に示します。

{"description":"Validation Failed",
 "errors":[
    {"field":"emailAddress","message":"not a well-formed email address"}
    {"field":"phoneNumber","message":"The phone number supplied was null."},
    {"field":"password","message":"may not be null"}]}

基本的な ConstrainViolationException に基づいて応答エンティティを返す簡単で汚い例を次に示しますが、このクラスのインスタンスに「フィールド」要素と「メッセージ」要素を簡単に追加する方法を理解できると思います。

public class RestValidationErrorEntity {

    public static Response createResponseOrThrow( ConstraintViolationException e ) {
        return Response
            .status( Response.Status.BAD_REQUEST )
            .entity( new RestValidationErrorEntity( e ) )
            .build();
    }

    public String description = "Validation Failed";
    public List<Detail> errors = new ArrayList<>();

    public RestValidationErrorEntity( ConstraintViolationException e ) {
        for ( ConstraintViolation<?> violation : e.getConstraintViolations() ) {
            errors.add(
                new Detail(
                    violation.getPropertyPath().toString(), violation.getMessage()
                ) );
        }
    }

    public static class Detail {
        public String field;
        public String message;

        Detail( String field, String message ) {
            this.message = message;
            this.field = field;
        }
    }
}
于 2013-01-14T21:22:25.157 に答える