restful consume json jersey jackson jax-rs

consume - Custom ExceptionMapper for Jersey no funciona para entradas JSON no válidas



jersey restful json (3)

Tengo el siguiente recurso que consume un JSON asignado a un POJO.

@Path("example") public class ExampleResource { @POST @Consumes(MediaType.APPLICATION_JSON) public Response addThesis(MyObject myObject) { return Response.ok().entity("Test").build(); } }

Aquí está la clase POJO:

public class MyObject { private String title; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }

Cuando envío una solicitud POST con el cuerpo {"title": "Test title"} todo funciona bien. La respuesta es Prueba , como se esperaba. Sin embargo, cuando cambio la solicitud a {"titlee": "Test title"}, el servidor responde con esto:

Campo no reconocido "titlee" (clase com.my.package.MyObject), no marcado como ignorable (una propiedad conocida: "título")) en [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@6dc6a46a; línea: 2, columna: 11] (a través de la cadena de referencia: com.my.package.MyObject ["titlee"])

Obviamente, esta es una excepción lanzada y devuelta por Jersey. ¿Cómo puedo interceptar esta excepción y devolver un código y un mensaje de estado personalizado?

Lo que he intentado hasta ahora es implementar mi propio ExceptionMapper:

@Provider public class MyJsonExceptionMapper implements ExceptionMapper<JsonProcessingException> { public Response toResponse(JsonProcessingException e) { return Response.status(400).entity("JSON Processing Error").build(); } }

Lamentablemente, la respuesta sigue siendo la misma. Cuando implemente un ExceptionMapper para una excepción personalizada y arroje la excepción correspondiente en el método de recursos, todo funciona bien. Supongo que esto tiene que ver con el ExceptionMapper predeterminado para JsonProcessingException sobre el mío propio. Luego traté de crear un asignador genérico ("implementa ExceptionMapper"), pero nuevamente no tuve éxito.

Miré literalmente a todas partes y probé muchas cosas, incluyendo extender ResourceConfig y registrar mi mapper, pero nada ha funcionado hasta ahora.

Más información que podría ayudar a reducir el problema: estoy usando Grizzly2 como el servidor HTTP que estoy implementando como un JAR Grasa.

La parte de dependencia de mi pom.xml se ve así:

<dependencies> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> <version>2.24</version> </dependency> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-grizzly2-http</artifactId> <version>2.24</version> </dependency> </dependencies>

Cualquier consejo es muy apreciado.


Ok, esto es tonto y hack-ish, pero funcionó para mí:

register(JacksonJaxbJsonProvider.class);

Esto se debe al siguiente "buen comportamiento predeterminado" en el punto de entrada de la función Jackson:

if (!config.isRegistered(JacksonJaxbJsonProvider.class)) { // add the default Jackson exception mappers context.register(JsonParseExceptionMapper.class); context.register(JsonMappingExceptionMapper.class);

:(

Pero, aún preferiría una respuesta que corrige el problema "de verdad", es decir. sin prerregistrar los componentes para que la característica no pueda configurarlos adecuadamente ...


Usamos JAX-RS en Wildfly para implementar nuestros servicios web y utilizamos lo siguiente para lograr lo que está tratando de hacer con Jersey on Glassfish. Tal vez tiene características similares que puedes buscar. Nuestros pasos son:

  • El servicio es un EJB sin estado, usa el interceptor EJB para atrapar la excepción y rellenar el objeto del alcance de la solicitud con detalles
  • Implemente un PostProcessInterceptor que lea desde el objeto del alcance de la solicitud y modifique la respuesta antes de que el servicio regrese. (Esto es específico de JAX-RS)

También me enfrenté a este problema. Si JacksonFeature está registrado, simplemente puede registrar JacksonJaxbJsonProvider como una solución alternativa.

Cuando JacksonFeature encuentra en el classpath, Jersey lo descubre automáticamente. Otro enfoque para solucionarlo es deshabilitar el descubrimiento automático al establecer ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE en true . Como resultado de esto, deberá registrar otras funciones de forma manual.

Alternativamente, puedes deshacerte del artefacto jersey-media-json-jackson y utilizar el jackson-jaxrs-json-provider . Con esto, se deshará de JacksonFeature y luego podrá registrar sus propios mapeadores de excepciones.

Una última opción y probablemente lo que parece ser la solución correcta (como se señaló en la respuesta de Kysil Ivan) puede escribir su propio mapeador de excepciones y luego darle una alta prioridad, como 1 . Si usa el descubrimiento automático, simplemente @Provider con @Provider y @Priority :

@Provider @Priority(1) public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> { ... }

Si registra manualmente su proveedor, puede darle a su proveedor una prioridad vinculante :

@ApplicationPath("/") public class MyResourceConfig extends ResourceConfig { public MyResourceConfig() { register(JsonParseExceptionMapper.class, 1); } }

Vea esta respuesta para más detalles.