tutorial servicios servicio restful para español ejemplo crear consumir consume cliente java rest jpa jersey bean-validation

java - restful - ¿Cómo manejar la validación de recursos en los servicios web REST?



java consume rest service json (4)

Ahora puede usar Jersey 2.0 para validar argumentos de recursos a través de JSR-303 / JSR-349.

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

Estoy creando un servicio web REST en Java utilizando Spring, Jersey e Hibernate (JPA).

Ahora estoy tratando de agregar soporte para la validación en mis recursos. JSR-303 (validación de Bean) apareció naturalmente como una opción adecuada (estoy usando Hibernate Validator que es la implementación de referencia de JSR-303) Sin embargo, estoy tratando de consolidar algunos conceptos primero.

Me parece que hay al menos dos tipos de validaciones posibles:

  • Validación regular en campos , por ejemplo, verifique que una propiedad no sea nula, verifique si una propiedad de String es un correo electrónico válido, verifique si una propiedad de Integer es mayor que 10 , etc. Esto funciona como se espera He registrado un JAX-RS ExceptionMapper que mapea javax.validation.ConstraintViolationException en las respuestas HTTP adecuadas.
  • Validación de integridad de datos

Explicaré exactamente lo que quiero decir con "Validación de integridad de datos" con un ejemplo. Esto sucede cuando hay relaciones entre dos o más recursos. Imagina dos recursos: un Product y una Category . Un Product tiene una Category . Cuando el cliente envía al servidor la representación del Product a crear (una solicitud POST HTTP), debe informar a la Category del producto. El cliente debe conocer las categorías de antemano, por supuesto. Imagina en JSON algo como:

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

Bueno, la categoría con id 123 podría no existir. Si intentamos insertar esto en la base de datos, obviamente obtenemos una excepción relacionada con la clave externa. Entonces, asumo que tenemos que validar estos problemas y devolver un mensaje adecuado al cliente, al igual que en las validaciones de propiedades regulares.

Ahora, mis principales preguntas son:

  1. Ahora mismo estoy realizando la validación en el nivel de acceso a datos, a través de la integración de JPA con la validación de Bean. ¿Deben realizarse las validaciones antes / después de los procesos de serialización , antes / después de las operaciones de la base de datos o ambos ?
  2. ¿Cómo manejar las validaciones de integridad de datos ? ¿A mano? (es decir, consultando explícitamente la base de datos que verifica la integridad de los datos) ¿O deberíamos intentar insertarlo de todos modos y luego detectar excepciones en la base de datos (o DAO)? La validación de frijoles no tiene nada que ver con este tipo de validación, ¿verdad?
  3. Si tiene alguna experiencia con JAX-RS / REST y Bean Validation, me encantaría que me lo hiciera saber. ¿Usando grupos?

Estas preguntas están algo relacionadas con Java, pero también esperaba obtener algunas perspectivas nuevas sobre estos asuntos. Algunas tecnologias independientes. :) Sería fantástico si pudiera proporcionar sus propias soluciones para estos problemas en sus servicios web REST.


La solución terminó siendo la subclasificación de JacksonJaxbJsonProvider de Jackson, que implementa un MessageBodyReader JAX-RS y MessageBodyWriter . Me inspiré en el increíble enfoque del dropwizard . En este proveedor, necesitamos inyectar una instancia de Validator (utilicé Spring for Injection e Hibernate Validator para la implementación de JSR-303). Si usa Hibernate ORM, no olvide desactivar la validación de la entidad, de lo contrario estará validando la misma entidad dos veces. Aunque puede ser lo que se desee.

Luego, en este MessageBodyReader subclasificado, valido el objeto y lanzo una InvalidEntityException personalizada con los errores del validador. También creé un JAX-RS ExceptionMapper<InvalidEntityException> que asigna cada InvalidEntityException a una respuesta HTTP adecuada. En mi caso, devolví una Solicitud incorrecta y un objeto JSON que contenía la descripción de los errores.

Tenga en cuenta que este MessageBodyReader comprueba las anotaciones @Valid y @Validated . Esto significa que soporta correctamente grupos. Esto es importante porque probablemente no queremos hacer el mismo tipo de validación en toda nuestra aplicación. Un ejemplo es cuando queremos hacer una actualización parcial (PUT). O, por ejemplo, una propiedad de identificación debe ser nula en una solicitud POST pero no nula en ningún otro lugar.

Las validaciones de integridad de datos aún no se han tratado completamente. Pero estoy planeando capturar las excepciones de la base de datos y convertirlas a mis propias excepciones de dominio (por ejemplo, una excepción DataIntegrityException ), ya que me parece más eficiente y DataIntegrityException .

ACTUALIZAR:

Desde JAX-RS 2, la forma recomendada de hacer esto es usar su soporte de Validación de Bean. Consulte aquí: https://jersey.java.net/documentation/latest/bean-validation.html


Puede hacer uso de los jersey filters de jersey filters , donde puede hacer algunas validaciones en los datos de su solicitud.

Bueno, la categoría con id 123 podría no existir. Si intentamos insertar esto en la base de datos, obviamente obtenemos una excepción relacionada con la clave externa.

Para tales casos, uno puede confiar en las validaciones en el nivel de acceso a datos. Pero si desea responder a su cliente de forma sincrónica, generalmente es mejor tener esta lógica de negocios expuesta por alguna API de servicio. es decir, puede tener una API como isValidCategory(int id) , que se puede consultar en un nivel más alto que DAO para que no tenga que esperar hasta que la capa de acceso a datos encuentre un error / excepción. Obviamente, esto todavía puede significar una búsqueda en la base de datos (depende de su sistema), pero optimizarlo para mejorar su tiempo de respuesta usando Caching o algún otro mecanismo es un problema completamente diferente.

Hablando de los validadores de frijoles, puede echar un vistazo a Hibernate Validator, que es una implementación JSR 303.


Oval es el mejor paquete para evaluar un objeto. Es muy útil generar una afirmación de prueba unitaria y una prueba automatizada.