ジャージーでのBean検証

1概要

このチュートリアルでは、オープンソースフレームワークhttps://jersey.github.io/[Jersey]を使ったBean Validationを見ていきます。

前回の記事ですでに説明したように、 JerseyはRESTful Webサービスを開発するためのオープンソースフレームワークです。 https://www.baeldung.com/jersey-restの紹介で、Jerseyの詳細を知ることができます。 -api-with-spring[JerseyとSpringでAPIを作成します。]

2ジャージでのBean検証

検証とは、いくつかのデータが1つ以上の事前定義された制約に従うことを検証するプロセスです。もちろん、これはほとんどのアプリケーションで非常に一般的な使用例です。

Java Bean バリデーション フレームワーク(JSR-380)は、Javaでこの種の操作を処理するための事実上の標準となっています。 Java Bean Validationの基本についておさらいするには、以前のhttps://www.baeldung.com/javax-validation[チュートリアル]を参照してください。

  • Jerseyには、Bean Validation ** をサポートするための拡張モジュールが含まれています。この機能をアプリケーションで使用するには、まずそれを構成する必要があります。次のセクションでは、アプリケーションを設定する方法について説明します。

3アプリケーション設定

それでは、https://www.baeldung.com/jersey-mvc[Jersey MVC Support]の優れた記事から、単純なFruit APIの例を基にしてみましょう。

3.1. Mavenの依存関係

まず、Bean Validation依存関係を pom.xml に追加しましょう。

<dependency>
    <groupId>org.glassfish.jersey.ext</groupId>
    <artifactId>jersey-bean-validation</artifactId>
    <version>2.27</version>
</dependency>

最新版はhttps://search.maven.org/classic/#search%7Cga%7C1%7Cjersey-bean-validation[Maven Central]から入手できます。

3.2. サーバーの設定

Jerseyでは、通常、使用したい拡張機能をカスタムリソース設定クラスに登録します。

ただし、Bean検証拡張機能の場合は、この登録をする必要はありません。幸い、これはJerseyフレームワークが自動的に登録する数少ない拡張機能の1つです。

最後に、検証エラーをクライアントに送信するために、カスタムリソース設定にサーバープロパティを追加します。

public ViewApplicationConfig() {
    packages("com.baeldung.jersey.server");
    property(ServerProperties.BV__SEND__ERROR__IN__RESPONSE, true);
}

4 JAX-RSリソースメソッドの検証

このセクションでは、制約アノテーションを使用して入力パラメータを検証する2つの異なる方法について説明します。

ビルトインBean Validation API制約の使用

  • カスタム制約とバリデータの作成

4.1. 組み込み制約アノテーションの使用

組み込みの制約アノテーションを見ることから始めましょう:

@POST
@Path("/create")
@Consumes(MediaType.APPLICATION__FORM__URLENCODED)
public void createFruit(
    @NotNull(message = "Fruit name must not be null") @FormParam("name") String name,
    @NotNull(message = "Fruit colour must not be null") @FormParam("colour") String colour) {

    Fruit fruit = new Fruit(name, colour);
    SimpleStorageService.storeFruit(fruit);
}

この例では、2つのフォームパラメータ name colour を使用して新しい Fruit を作成します。 Bean Validation APIの一部である @ NotNull アノテーションを使用します。

これにより、フォームパラメータにnullではない単純な制約が課されます。 パラメータの1つが null の場合、アノテーション内で宣言されたメッセージが返されます

当然、これをユニットテストで実証します。

@Test
public void givenCreateFruit__whenFormContainsNullParam__thenResponseCodeIsBadRequest() {
    Form form = new Form();
    form.param("name", "apple");
    form.param("colour", null);
    Response response = target("fruit/create").request(MediaType.APPLICATION__FORM__URLENCODED)
        .post(Entity.form(form));

    assertEquals("Http Response should be 400 ", 400, response.getStatus());
    assertThat(response.readEntity(String.class), containsString("Fruit colour must not be null"));
}

上記の例では、フルーツリソースをテストするために JerseyTest サポートクラスを使用しています。 POSTリクエストにnull colour を付けて送信し、レスポンスに予想されるメッセージが含まれていることを確認します。

組み込みの検証制約の一覧については、https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html__single/#section-builtin -constraintsを参照してください。

4.2. カスタム制約アノテーションを定義する

時にはもっと複雑な制約を課す必要があります。これは、独自のカスタムアノテーションを定義することによって実現できます。

簡単なFruit APIの例を使用して、すべてのフルーツに有効なシリアル番号があることを検証する必要があるとしましょう。

@PUT
@Path("/update")
@Consumes("application/x-www-form-urlencoded")
public void updateFruit(@SerialNumber @FormParam("serial") String serial) {
   //...
}

この例では、パラメータ serial は、次に定義する @ SerialNumber で定義された制約を満たす必要があります。

まず、制約アノテーションを定義します。

@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = { SerialNumber.Validator.class })
    public @interface SerialNumber {

    String message()

    default "Fruit serial number is not valid";

    Class<?>[]groups() default {};

    Class<? extends Payload>[]payload() default {};
}

次に、バリデータクラス SerialNumber.Validator を定義します。

public class Validator implements ConstraintValidator<SerialNumber, String> {
    @Override
    public void initialize(SerialNumber serial) {
    }

    @Override
    public boolean isValid(String serial,
        ConstraintValidatorContext constraintValidatorContext) {

        String serialNumRegex = "^\\d{3}-\\d{3}-\\d{4}$";
        return Pattern.matches(serialNumRegex, serial);
    }
}

.

  • 最後に、 isValid メソッドのカスタム検証ロジック** 。

5リソース検証

  • さらに、Bean Validation APIでは、 @ Valid アノテーション** を使ってオブジェクトを検証することもできます。

次のセクションでは、このアノテーションを使ってリソースクラスを検証する2つの異なる方法について説明します。

  • まず、リソースの検証を要求する

  • 第二に、レスポンスリソースの検証

Fruit オブジェクトに @ Min アノテーションを追加することから始めましょう:

@XmlRootElement
public class Fruit {

    @Min(value = 10, message = "Fruit weight must be 10 or greater")
    private Integer weight;
   //...
}

5.1. リソース検証の要求

まず最初に、 FruitResource クラスで @ Valid を使用して検証を有効にします。

@POST
@Path("/create")
@Consumes("application/json")
public void createFruit(@Valid Fruit fruit) {
    SimpleStorageService.storeFruit(fruit);
}

上記の例では、10未満の重さでフルーツを作成しようとすると、検証エラーになります。

5.2. レスポンスリソースの検証

同様に、次の例では、レスポンスリソースを検証する方法を説明します。

@GET
@Valid
@Produces("application/json")
@Path("/search/{name}")
public Fruit findFruitByName(@PathParam("name") String name) {
    return SimpleStorageService.findByName(name);
}

注意してください、我々は同じ @ Valid アノテーションをどのように使用するか。しかし今回は、応答が有効であることを確認するためにリソースメソッドレベルでそれを使用します。

6. カスタム例外ハンドラ

この最後の部分では、カスタム例外ハンドラの作成方法について簡単に説明します。これは、特定の制約に違反した場合にカスタムレスポンスを返したいときに便利です。

FruitExceptionMapper を定義することから始めましょう。

public class FruitExceptionMapper implements ExceptionMapper<ConstraintViolationException> {

    @Override
    public Response toResponse(ConstraintViolationException exception) {
        return Response.status(Response.Status.BAD__REQUEST)
            .entity(prepareMessage(exception))
            .type("text/plain")
            .build();
    }

    private String prepareMessage(ConstraintViolationException exception) {
        StringBuilder message = new StringBuilder();
        for (ConstraintViolation<?> cv : exception.getConstraintViolations()) {
            message.append(cv.getPropertyPath() + " " + cv.getMessage() + "\n");
        }
        return message.toString();
    }
}

まず最初に、カスタム例外マッピングプロバイダを定義します。これを行うために、 ConstraintViolationException を使用して ExceptionMapper インターフェースを実装します。

  • 。**

また、この簡単な例では、すべての違反を繰り返して、応答で送り返す各プロパティとメッセージを追加します。

  • 次に、私たちのカスタム例外マッパーを使うためには、私たちのプロバイダーを登録する必要があります** :

@Override
protected Application configure() {
    ViewApplicationConfig config = new ViewApplicationConfig();
    config.register(FruitExceptionMapper.class);
    return config;
}

最後に、例外ハンドラが動作していることを示すために無効な Fruit を返すためのエンドポイントを追加します。

@GET
@Produces(MediaType.TEXT__HTML)
@Path("/exception")
@Valid
public Fruit exception() {
    Fruit fruit = new Fruit();
    fruit.setName("a");
    fruit.setColour("b");
    return fruit;
}

7. 結論

要約すると、このチュートリアルでは、Jersey Bean Validation API拡張機能について説明しました。

まず、JerseyでBean Validation APIを使用する方法を紹介することから始めました。また、サンプルWebアプリケーションの設定方法についても見てきました。

最後に、Jerseyで検証を行ういくつかの方法と、カスタム例外ハンドラを作成する方法を調べました。

いつものように、この記事の完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/jersey[GitHubで利用可能]です。