Estoy aprendiendo JAX-RS (también conocido como JSR-311) usando Jersey. He creado con éxito un recurso raíz y estoy jugando con los parámetros:
@Path("/hello")
public class HelloWorldResource {
@GET
@Produces("text/html")
public String get(
@QueryParam("name") String name,
@QueryParam("birthDate") Date birthDate) {
// Return a greeting with the name and age
}
}
Esto funciona muy bien y maneja cualquier formato en el entorno local actual que entiende el constructor Fecha (Cadena) (como AAAA / mm / dd y mm / dd / AAAA). Pero si proporciono un valor que no es válido o no se entiende, obtengo una respuesta 404.
Por ejemplo:
GET /hello?name=Mark&birthDate=X
404 Not Found
¿Cómo puedo personalizar este comportamiento? ¿Quizás un código de respuesta diferente (probablemente "400 Solicitud incorrecta")? ¿Qué pasa con el registro de un error? ¿Quizás agregar una descripción del problema ("formato de fecha incorrecta") en un encabezado personalizado para ayudar a solucionar problemas? ¿O devolver una respuesta de error completa con detalles, junto con un código de estado 5xx?
ExceptionMapper
interfaz (que es un enfoque mejor que extenderlo). Ver más aquí vvirlan.wordpress.com/2015/10/19/…Crear por encima de la clase. Esto manejará 404 (NotFoundException) y aquí en el método toResponse puede dar su respuesta personalizada. Del mismo modo, hay ParamException, etc., que necesitaría asignar para proporcionar respuestas personalizadas.
fuente
Jersey arroja una com.sun.jersey.api.ParamException cuando no logra desarmar los parámetros, por lo que una solución es crear un ExceptionMapper que maneje estos tipos de excepciones:
fuente
También podría escribir una clase reutilizable para variables anotadas QueryParam
luego úsalo así:
Aunque el manejo de errores es trivial en este caso (arrojando una respuesta 400), el uso de esta clase le permite factorizar el manejo de parámetros en general, lo que podría incluir el registro, etc.
fuente
DateParam
anterior que envuelva un enorg.joda.time.DateTime
lugar dejava.util.Calendar
. Usas eso con en@QueryParam
lugar deDateTime
sí mismo.JodaModule
que se puede registrar con elObjectMapper
registerModules
método. Puede manejar todas las conversiones de tipo joda.com.fasterxml.jackson.datatype.joda.JodaModule
Una solución obvia: tome una Cadena, conviértala en Fecha usted mismo. De esa manera puede definir el formato que desee, capturar excepciones y volver a lanzar o personalizar el error que se envía. Para el análisis, SimpleDateFormat debería funcionar bien.
Estoy seguro de que también hay formas de conectar controladores para tipos de datos, pero tal vez un poco de código simple es todo lo que necesita en este caso.
fuente
También me gusta que StaxMan probablemente implemente ese QueryParam como una Cadena, luego maneje la conversión, volviendo a lanzarla según sea necesario.
Si el comportamiento específico de la localidad es el comportamiento deseado y esperado, usaría lo siguiente para devolver el error 400 MALA SOLICITUD:
throw new WebApplicationException(Response.Status.BAD_REQUEST);
Consulte JavaDoc para javax.ws.rs.core.Response.Status para obtener más opciones.
fuente
La documentación de @QueryParam dice
Si desea controlar qué respuesta va al usuario cuando el parámetro de consulta en forma de cadena no se puede convertir a su tipo T, puede lanzar WebApplicationException. Dropwizard viene con las siguientes clases de * Param que puedes usar para tus necesidades.
BooleanParam, DateTimeParam, IntParam, LongParam, LocalDateParam, NonEmptyStringParam, UUIDParam. Ver https://github.com/dropwizard/dropwizard/tree/master/dropwizard-jersey/src/main/java/io/dropwizard/jersey/params
Si necesita Joda DateTime, simplemente use Dropwizard DateTimeParam .
Si la lista anterior no satisface sus necesidades, defina la suya ampliando AbstractParam. Anular el método de análisis. Si necesita control sobre el cuerpo de respuesta de error, anule el método de error.
Un buen artículo de Coda Hale sobre esto está en http://codahale.com/what-makes-jersey-interesting-parameter-classes/
El constructor de fecha (String arg) está en desuso. Usaría clases de fecha Java 8 si está en Java 8. De lo contrario, se recomienda la fecha de joda.
fuente
Este es el comportamiento correcto en realidad. Jersey intentará encontrar un controlador para su entrada e intentará construir un objeto a partir de la entrada proporcionada. En este caso, intentará crear un nuevo objeto Date con el valor X proporcionado al constructor. Como esta es una fecha no válida, por convención Jersey devolverá 404.
Lo que puede hacer es reescribir y poner la fecha de nacimiento como una Cadena, luego intentar analizar y, si no obtiene lo que desea, puede lanzar cualquier excepción que desee mediante cualquiera de los mecanismos de mapeo de excepciones (hay varios )
fuente
Estaba enfrentando el mismo problema.
Quería detectar todos los errores en un lugar central y transformarlos.
El siguiente es el código de cómo lo manejé.
Cree la siguiente clase que implementa
ExceptionMapper
y agregue@Provider
anotaciones en esta clase. Esto manejará todas las excepciones.Anule el
toResponse
método y devuelva el objeto de Respuesta poblado con datos personalizados.fuente
Enfoque 1: ampliando la clase WebApplicationException
Cree una nueva excepción extendiendo WebApplicationException
Ahora lanza 'RestException' cuando sea necesario.
Puede ver la solicitud completa en este enlace .
Enfoque 2: Implementar ExceptionMapper
El siguiente mapeador maneja la excepción del tipo 'DataNotFoundException'
Puede ver la solicitud completa en este enlace .
fuente
Solo como una extensión de la respuesta de @Steven Lavine en caso de que desee abrir la ventana de inicio de sesión del navegador. Me resultó difícil devolver correctamente la Respuesta ( Autenticación HTTP MDN ) del Filtro en caso de que el usuario aún no se haya autenticado
Esto me ayudó a construir la Respuesta para forzar el inicio de sesión del navegador, tenga en cuenta la modificación adicional de los encabezados. Esto establecerá el código de estado en 401 y establecerá el encabezado que hace que el navegador abra el diálogo de nombre de usuario / contraseña.
fuente