web-dev-qa-db-fra.com

Comment gérer la validation des ressources dans REST services Web?

Je suis en train de construire un service Web REST en Java avec Spring, Jersey et Hibernate (JPA).

J'essaie maintenant d'ajouter un support pour la validation dans mes ressources. JSR-303 (validation de haricot) est naturellement apparu comme un choix approprié (j'utilise Hibernate Validator, qui est l'implémentation de référence de JSR-303). Cependant, j'essaie d'abord de consolider certains concepts.

Il me semble qu’il existe au moins deux types de validations possibles:

  • Validation régulière sur les champs, par exemple. vérifiez qu'une propriété n'est pas nulle, vérifiez si une propriété String est un courrier électronique valide, vérifiez si une propriété Integer est supérieure à 10, etc. Cela fonctionne comme prévu. J'ai enregistré un ExceptionMapper JAX-RS qui mappe les javax.validation.ConstraintViolationException dans les réponses HTTP appropriées.
  • Validation de l'intégrité des données

Je vais expliquer ce que je veux dire exactement par "Validation de l'intégrité des données" avec un exemple. Cela se produit lorsqu'il existe des relations entre deux ressources ou plus. Imaginez deux ressources: une Product et une Category. Une Producta une Category. Lorsque le client envoie au serveur la représentation de la Product à créer (une requête HTTP POST), il doit informer la Category du produit. Le client doit bien sûr connaître les catégories à l’avance. Imaginez dans JSON quelque chose comme:

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

Eh bien, la catégorie avec id 123 pourrait ne pas exister. Si nous essayons d'insérer ceci dans la base de données, nous obtenons évidemment une exception liée à la clé étrangère. Je suppose donc que nous devons valider ces problèmes et renvoyer un message approprié au client, tout comme dans les validations de propriété normales.


Maintenant, mes questions principales sont:

  1. Actuellement, je réalise la validation au niveau d'accès aux données, grâce à l'intégration de JPA avec Bean Validation. Les validations doivent-elles être effectuées avant/après les processus de sérialisation _, avant/après les opérations de base de données ou les deux?
  2. Comment gérer Validations d'intégrité des données? Manuellement? (c'est-à-dire consulter explicitement la base de données en vérifiant l'intégrité des données) ou devrions-nous simplement essayer de l'insérer de toute façon, puis intercepter les exceptions de base de données (ou DAO)? Bean Validation n'a rien à voir avec ce type de validation, non?
  3. Si vous avez une expérience avec JAX-RS/REST et la validation de haricots, je serais heureux si vous me le faites savoir. Utiliser des groupes?

Ces questions sont un peu liées à Java, mais j’espérais aussi avoir de nouvelles perspectives sur ces questions. Certains indépendants de la technologie. :) Ce serait formidable si vous pouviez apporter vos propres solutions à ces problèmes sur vos services Web REST.

20
miguelcobain

La solution a fini par sous-classer le JacksonJaxbJsonProvider de Jackson qui implémente un JAX-RS MessageBodyReader et MessageBodyWriter. J'ai été inspiré par la surprenante approche de dropwizard . Dans ce fournisseur, nous devons en quelque sorte injecter une instance de Validateur (j'ai utilisé Spring pour Injection et Hibernate Validator pour l'implémentation JSR-303). Si vous utilisez Hibernate ORM, n'oubliez pas de désactiver la validation d'entité, sinon vous validerez la même entité deux fois. Ce peut être ce qui est désiré, cependant.

Ensuite, dans cette sous-classe MessageBodyReader, je valide l'objet et jette un nom personnalisé InvalidEntityException avec les erreurs du validateur. J'ai également créé un ExceptionMapper<InvalidEntityException> JAX-RS qui mappe chaque InvalidEntityException en une réponse HTTP appropriée. Dans mon cas, j'ai renvoyé une requête incorrecte et un objet JSON contenant la description des erreurs.

Notez que ce MessageBodyReader vérifie les annotations @Valid et @Validated. Cela signifie qu'il prend correctement en charge les groupes. Ceci est important car nous ne voulons probablement pas faire le même type de validation sur l’ensemble de notre application. Un exemple est lorsque nous voulons faire une mise à jour partielle (PUT). Ou, par exemple, une propriété id doit être null dans une demande POST mais non nulle partout ailleurs.

Intégrité des données Les validations ne sont pas encore complètement traitées. Mais je prévois attraper les exceptions de base de données et les convertir en mes propres exceptions de domaine (disons un DataIntegrityException) car cela me semble plus efficace et plus ou moins couplé.


METTRE À JOUR:

Depuis JAX-RS 2, la méthode recommandée consiste à utiliser le support de validation de bean. Vérifiez ici: https://jersey.Java.net/documentation/latest/bean-validation.html

8
miguelcobain

Vous pouvez maintenant utiliser Jersey 2.0 pour la validation des arguments de ressources via JSR-303/JSR-349.

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

6
yeforriak

Vous pouvez utiliser jersey filters, où vous pouvez effectuer des validations sur les données de votre demande.

Eh bien, la catégorie avec l'ID 123 pourrait ne pas exister. Si nous essayons d'insérer ceci dans la base de données, nous obtiendrons évidemment une exception liée à la clé étrangère.

Dans ce cas, on peut s’appuyer sur les validations au niveau d’accès aux données. Toutefois, si vous souhaitez répondre à votre client de manière synchrone, il est généralement préférable d'exposer cette logique métier à l'aide d'une API de service. Par exemple, vous pouvez avoir une API telle que isValidCategory(int id), qui peut être interrogée à un niveau supérieur à celui de DAO afin de ne pas avoir à attendre que la couche d'accès aux données rencontre une erreur/une exception. Évidemment, cela peut toujours signifier une consultation de base de données (dépend de votre système), mais l'optimisation de cette opération pour améliorer votre temps de réponse à l'aide de la mise en cache ou d'un autre mécanisme est un problème totalement différent.

En parlant de validateurs de beans, vous pouvez jeter un oeil à Hibernate Validator qui est une implémentation JSR 303.

1
Swapnil

Ovale est le meilleur package pour évaluer un objet. Il est très utile de générer une assertion de test unitaire et un test automatisé.

0
مصطفی