web-dev-qa-db-ja.com

REST Webサービスでリソース検証を処理する方法は?

REST webservice in Java Spring、Jersey、およびHibernate(JPA)を使用して)を構築しています。

現在、私のリソースに検証のサポートを追加しようとしています。 JSR-303(Bean validation)は適切な選択肢として自然に登場しました(私はJSR-303のリファレンス実装であるHibernate Validatorを使用しています)。ただし、最初にいくつかの概念を統合しようとしています。

少なくとも2種類の可能な検証があるように思えます。

  • フィールドの定期的な検証、例:プロパティがnullではないことを確認し、Stringプロパティが有効な電子メールであるかどうかを確認し、Integerプロパティが10より大きいかどうかを確認します。これは機能しています予想通り。 javax.validation.ConstraintViolationExceptionを適切なHTTP応答にマップするJAX-RS ExceptionMapperを登録しました。
  • データの整合性の検証

「データ整合性検証」の意味を具体的に例を挙げて説明します。これは、2つ以上のリソース間に関係がある場合に発生します。 2つのリソースを想像してください:ProductCategory。 A Producthas a Category。クライアントがサーバーにProductの表現を送信して作成する場合(POST HTTPリクエスト))、クライアントはCategoryに製品を通知する必要があります。もちろん、クライアントは事前にカテゴリを知っている必要があります。JSONで次のようなものを想像してください。

{
   "quantity": "10",
   "state": "PRODUCED",
   "category": {
      "id": "123"
   }
}

まあ、ID 123のカテゴリは存在しないかもしれません。これをデータベースに挿入しようとすると、明らかに外部キー関連の例外が発生します。したがって、通常のプロパティの検証と同様に、これらの問題を検証して適切なメッセージをクライアントに返す必要があると思います。


今、私の主な質問は次のとおりです。

  1. 現在、JPAとBean Validationの統合により、データアクセスレベルで検証を実行しています。検証を行う必要がありますシリアライズプロセスの前/後データベース操作の前/後または両方
  2. 処理方法データ整合性検証手動? (つまり、データの整合性をチェックするデータベースを明示的に調べます)または、とにかくそれを挿入してから、データベース(またはDAO)の例外をキャッチしようとする必要がありますか? Bean Validationは、この種の検証とは関係ありませんよね?
  3. JAX-RS/RESTおよびBean Validationの経験がある場合は、お知らせいただければ幸いです。グループを使用していますか?

これらの質問はJavaに多少関連していますが、これらの問題についていくつかの新しい視点を得ることも期待していました。テクノロジーに依存しないものもあります。 :) REST webservices。でこれらの問題に対する独自のソリューションを提供できれば素晴らしいと思います

20
miguelcobain

解決策は、JAX-RS JacksonJaxbJsonProviderMessageBodyReaderを実装するJacksonのMessageBodyWriterをサブクラス化することになった。私は素晴らしい dropwizardのアプローチ に触発されました。このプロバイダーでは、なんとかしてValidatorインスタンスを挿入する必要があります(私はSpringを注入に、Hibernate ValidatorをJSR-303実装に使用しました)。 Hibernate ORMを使用する場合は、エンティティの検証を無効にすることを忘れないでください。そうしないと、同じエンティティを2回検証することになります。しかし、それは望ましいことかもしれません。

次に、このサブクラス化されたMessageBodyReaderでオブジェクトを検証し、バリデーターのエラーを含むカスタムInvalidEntityExceptionをスローします。 JAX-RSも作成しましたExceptionMapper<InvalidEntityException>すべてのInvalidEntityExceptionを適切なHTTP応答にマップします。私の場合、私はBad Requestとエラーの説明を含むJSONオブジェクトを返しました。

このMessageBodyReaderが@Validおよび@Validatedアノテーション。つまり、グループを正しくサポートします。アプリケーション全体で同じ種類の検証を実行したくないので、これは重要です。例は、部分更新(PUT)を実行する場合です。または、たとえば、POSTリクエストではidプロパティはnullでなければなりませんが、それ以外の場所ではnull以外にする必要があります。

データの整合性の検証はまだ完全には扱われていません。しかし、データベースの例外をキャッチして自分のドメインの例外(DataIntegrityExceptionなど)に変換することを計画しています。


UPDATE:

JAX-RS 2以降、これを行うための推奨される方法は、Bean検証サポートを使用することです。ここを確認してください: https://jersey.Java.net/documentation/latest/bean-validation.html

8
miguelcobain

JSR-303/JSR-349を介したリソース引数の検証にJersey 2.0を使用できるようになりました。

https://jersey.Java.net/documentation/latest/bean-validation.html#d0e9301

6
yeforriak

_jersey filters_を使用して、リクエストデータの検証を行うことができます。

まあ、ID 123のカテゴリは存在しないかもしれません。これをデータベースに挿入しようとすると、明らかに外部キー関連の例外が発生します。

このような場合、データアクセスレベルの検証に依存できます。ただし、クライアントに同期的に応答する場合は、通常、このビジネスロジックをサービスAPIで公開することをお勧めします。つまり、isValidCategory(int id)のようなAPIがあり、DAOよりも高いレベルでクエリできるため、データアクセスレイヤーでエラー/例外が発生するまで実際に待機する必要はありません。明らかに、これは依然としてデータベースルックアップを意味する場合があります(システムによって異なります)が、キャッシュやその他のメカニズムを使用して応答時間を改善するように最適化することは、まったく別の問題です。

Beanバリデーターについて言えば、JSR 303実装である Hibernate Validator を見ることができます。

1
Swapnil

Oval は、オブジェクトを評価するのに最適なパッケージです。単体テストのアサーションと自動テストを生成すると非常に便利です。

0
Mostafa