2012-03-23 32 views
15

estoy usando procesamiento integrada Jackson de Jersey para transformar JSON entrante a un POJO, por ejemplo:Jersey: Volviendo 400 error en lugar de 500 cuando se administra petición no válida cuerpo

@POST 
@Consumes(MediaType.APPLICATION_JSON) 
public Response newCustomer(CustomerRepresentation customer) 
{ 
... 
} 

Si un cliente envía JSON con campos no válidos Jersey actualmente devuelve un 500 Internal Server Error. En su lugar, me gustaría devolver un 400 Bad Request, preferiblemente con algún detalle significativo que indique qué campos son erróneos.

¿Alguna idea de cómo se podría lograr esto? (Por lo menos el retorno de una genérica 400 en lugar de la totalmente inadecuada 500?)

Actualización: Aquí está la excepción que se genera en el servidor, antes de que mi controlador se invoca:

javax.servlet.ServletException: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: 
Unrecognized field "this_isnt_a_known"_field" (Class com.redacted....), not marked as ignorable 
+0

'400' en realidad significa 'Solicitud incorrecta ', es decir, el servidor cree que el cliente ha enviado una solicitud incorrecta. Así que, semánticamente, no se ajusta a lo que quieres lograr. –

+0

Gracias por tomar mi resbalón. Tenía la intención de escribir "Solicitud incorrecta". Pregunta editada en consecuencia. – HolySamosa

+0

Jersey generalmente devuelve 400 si el cuerpo de la solicitud no es válido. ¿Estás seguro de que no falla en el cuerpo de tu método con un NPE o algo así? ¿Ves algún error y/o rastro de pila en los registros de tu servidor de aplicaciones? – TheArchitect

Respuesta

14

que finalmente fue capaz de solucionar este problema mediante la implementación de un ExceptionMapper para coger el UnrecognizedPropertyException tirado por Jackson y asignarla a un 400 Bad Request respuesta:

@Provider 
public class UnrecognizedPropertyExceptionMapper implements ExceptionMapper<UnrecognizedPropertyException> 
{ 

    @Override 
    public Response toResponse(UnrecognizedPropertyException exception) 
    { 
     return Response 
       .status(Response.Status.BAD_REQUEST) 
       .entity("'" + exception.getUnrecognizedPropertyName() + "' is an unrecognized field.") 
       .type(MediaType.TEXT_PLAIN) 
       .build(); 
    } 

} 
+0

Gracias también resolvió mi problema :) – AnujKu

+0

@HolySamosa Gracias por compartir esto. pero de alguna manera 'toResponse()' no se invoca. – agpt

+1

hey HolySamosa ... ¿Puede decirnos cómo se invoca toResponse()? Estoy atascado con este problema y no tenía ninguna solución para arrojar un error de 400 en lugar de 500. – ankit

1

que he tenido este mismo problema ... Desafortunadamente, no hay una buena forma de que sepa interceptar la excepción Jackson y generar su propio código de error.

Una opción que tiene es usar @JsonIgnoreProperties y luego validar estrictamente el objeto deserializado. Esto no le dirá si su remitente transmitió basura, pero si omitió los campos obligatorios, lo detectará.

No puedo encontrar ninguna forma de acceder al JSON real pasado, aparte de crear una clase @Provider para atrapar el JSON, validarlo y luego pasarlo a Jackson para su deserialización.

+0

Jersey puede pasar el JSON a su controlador como un JsonNode que nos permita validar el JSON bien formado, pero Jersey aún devolverá 500 para una solicitud que no es JSON (o eso supongo-- No lo he intentado aún). – HolySamosa

+1

Finalmente volví a trabajar en este tema y pude solucionarlo usando un ExceptionMapper. – HolySamosa

1

Probé mapeo estado 500 a estado 400 con la respuesta de HolySamosa pero la excepción no fue capturada por este asignador, y el estado todavía estaba siendo devuelto.

Después de la depuración encontré que JsonParseException se está lanzando y no UnrecognizedPropertyException. Esto se debe a que estaba enviando un texto basura (que no era JSON para nada).

Cuando envié un JSON adecuado desde el lado del cliente, con un formato que no era apropiado para mi DTO en el lado del servidor, obtuve UnrecognizedPropertyException. Así que hay dos casos para esto:

  • cuando envía basura que no es JSON y
  • cuando envía JSON, pero no es apropiado para su clase DTO.

Ahora estoy volviendo estado 400 para ambos.

2

En dropwizard land hay un ExceptionMapper llamado JsonProcessingExceptionMapper que tiene una funcionalidad similar a la que está buscando. Tal vez puedas usar eso para inspirarte sobre cómo abordar tu problema específico en un mundo que no sea dropwizard.

Cuestiones relacionadas