json - httpmediatypenotacceptableexception - not acceptable could not find acceptable representation
Spring MVC-HttpMediaTypeNotAcceptableException (12)
Sigo recibiendo este error HttpMediaTypeNotAcceptableException para las solicitudes AJAX cuando se usa con Spring MVC y JSON. El rastro de la pila completa del error es ...
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.writeWithMessageConverters(AnnotationMethodHandlerAdapter.java:1032)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.handleResponseBody(AnnotationMethodHandlerAdapter.java:972)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.getModelAndView(AnnotationMethodHandlerAdapter.java:921)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:438)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:863)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:792)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:851)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:756)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
poco google que hice muestra que la solicitud debe contener algo así como "accept: application / json", que sí tiene ... aquí están los encabezados de solicitud de firebug ...
Response Headers
Server Apache-Coyote/1.1
Content-Type text/html;charset=utf-8
Content-Length 2503
Date Thu, 25 Aug 2011 21:00:05 GMT
Connection close
Request Headers
Host localhost:8080
User-Agent Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.20) Gecko/20110803 Firefox/3.6.20 (.NET CLR 3.5.30729)
Accept application/json, text/javascript, */*; q=0.01
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 115
Connection keep-alive
X-Requested-With XMLHttpRequest
Referer http://localhost:8080/legaldirectory/index.html
Cookie JSESSIONID=5C97DA19AED4D5FA17F4A58470FAA93B
Ahora estoy completamente perdido en lo que está sucediendo aquí ... ¿Qué más puede salir mal aquí para obtener este error ...
Asegúrate de agregar ambos Jars de Jackson a classpath:
- jackson-core-asl-x.jar
- jackson-mapper-asl-x.jar
Además, debe tener lo siguiente en su archivo Spring xml:
<mvc:annotation-driven />
Asegúrese de tener lo siguiente en su archivo Spring xml:
<context:annotation-config/>
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter"/>
</list>
</property>
</bean>
y todos los artículos de su POJO deben tener getters / setters. Espero eso ayude
Como Alex insinuó en una de las respuestas, podría usar ContentNegotiationManagerFactoryBean para establecer el tipo de contenido predeterminado en "application / json", pero sentí que ese enfoque no era para mí.
Lo que intentaba hacer era publicar un formulario en un método como este
@RequestMapping(value = "/post/to/me", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public @ResponseBody MyJsonPOJO handlePostForm(@Valid @ModelAttribute("form") ValidateMeForm form, BindingResult bindingResult) throws ApiException {
Lo que en cambio decidí hacer fue cambiar el encabezado "Aceptar" de la solicitud del navegador a "application / json", haciendo que SpringMVC encuentre mi método.
Uso de la API de extracción de Javascript (aún no finalizada):
var form = new FormData();
form.append("myData", "data");
let fetchConfig = {
method: "POST",
body: form,
headers: {"Accept": "application/json"}
};
fetch("/post/to/me", fetchConfig)
.then(... // Javascript Promise API here
Et voilà! Ahora SpringMVC encuentra el método, valida el formulario y le permite devolver un JSON POJO.
De: http://georgovassilis.blogspot.ca/2015/10/spring-mvc-rest-controller-says-406.html
Tienes este Spring @RestController y asignó una URL que contiene un correo electrónico como parte de la ruta de la URL. Has trabajado astutamente en el problema del truncamiento de puntos [1] y estás listo para rodar. Y de repente, en algunas URL, Spring devolverá un 406 [2] que dice que el navegador solicitó un cierto tipo de contenido y Spring no puede serializar la respuesta a ese tipo de contenido. El punto es que has estado haciendo aplicaciones de Spring durante años e hiciste todas las declaraciones de MVC correctamente e incluiste a Jackson y básicamente estás estancado. Peor aún, escupirá ese error solo en algunos correos electrónicos en la ruta de la URL, sobre todo los que terminan en un dominio ".com".
@RequestMapping(value = "/agenda/{email:.+}", method = RequestMethod.GET)
public List<AgendaEntryDTO> checkAgenda(@PathVariable("email") String email)
El problema [3] es bastante complicado: el servidor de aplicaciones realiza alguna negociación de contenido y convence a Spring de que el navegador solicitó un contenido de "aplicación / x-msdownload" , a pesar de que no se haya presentado en la solicitud.
La solución es especificar un administrador de negociación de contenido para el contexto de la aplicación web:
<mvc:annotation-driven enable-matrix-variables="true"
content-negotiation-manager="contentNegotiationManager" />
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="defaultContentType" value="application/json" />
<property name="favorPathExtension" value="false" />
<property name="favorParameter" value="false" />
<property name="parameterName" value="mediaType" />
<property name="ignoreAcceptHeader" value="false" />
<property name="useJaf" value="false" />
</bean>
Debido a que este es el primer hit de Google para "HttpMediaTypeNotAcceptableException", me gustaría agregar otro problema con el que tropecé y que también dio como resultado HttpMediaTypeNotAcceptableException.
En mi caso, era un controlador que especificaba "produce", por ejemplo:
@RequestMapping(path = "/mypath/{filename}", method = RequestMethod.GET,
produces = { MediaType.APPLICATION_XML_VALUE }
porque quería servir un archivo XML. Al mismo tiempo, estoy usando una clase con "@ControllerAdvice" para capturar Excepciones, por ejemplo, si no se encontró el archivo solicitado. El controlador de excepción devolvía JSON para que la aplicación cliente (angular) pudiera mostrar el mensaje de error en algún lugar del SPA.
Ahora el controlador quería devolver XML pero el manejador de excepciones devolvía JSON, por lo que se generó HttpMediaTypeNotAcceptableException. Lo resolví agregando JSON como posible valor "produce":
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}
Espero que esto ayude a alguien más. :-)
En mi caso, solo agrega la anotación @ResponseBody
para resolver este problema.
En su clase Spring @Configuration que amplía WebMvcConfigurerAdapter, anule el método configureMessageConverters, por ejemplo:
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// http
HttpMessageConverter converter = new StringHttpMessageConverter();
converters.add(converter);
logger.info("HttpMessageConverter added");
// string
converter = new FormHttpMessageConverter();
converters.add(converter);
logger.info("FormHttpMessageConverter added");
// json
converter = new MappingJackson2HttpMessageConverter();
converters.add(converter);
logger.info("MappingJackson2HttpMessageConverter added");
}
Y el error desaparecerá
Intenta agregar jarras "jackson-databind" a pom.xml
`<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.databind-version}</version>
</dependency>`
Y produces ={MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}
en @RequestMapping
Es. @RequestMapping(value = "/api/xxx/{akey}/{md5}", produces ={MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}
@RequestMapping(value = "/api/contrassegno/{akey}/{md5}", produces ={MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE},...
Solo algo importante a tener en cuenta: las versiones Spring anteriores a 3.1.2 son compatibles con JACKSON 1.x y NO con JACKSON 2.x. Esto se debe a que al pasar de JACKSON 1.xa 2.x, se cambiaron los nombres de los paquetes de las clases. En JACKSON 1.x las clases están bajo org.codehaus.jackson mientras que en JACKSON 2.x están bajo com.fasterxml.jackson.
Para resolver este problema, comenzando con Spring 3.1.2 agregaron un nuevo MappingJackson2HttpMessageConverter para reemplazar MappingJacksonHttpMessageConverter.
Puede encontrar más detalles sobre problemas de compatibilidad en este enlace: las anotaciones de Jackson se ignoran en Spring
Tuve el mismo problema, pero me di cuenta de que, básicamente, lo que sucede cuando Spring está tratando de generar la respuesta intentará serializarlo de acuerdo con el tipo de medio que haya especificado y mediante el uso de métodos getter y setter en su clase
antes mi clase solía verse como a continuación
public class MyRestResponse{
private String message;
}
la solución se ve a continuación
public class MyRestResponse{
private String message;
public void setMessage(String msg){
this.message = msg;
}
public String getMessage(){
return this.message;
}
}
así es como me funcionó
en mi caso, favorPathExtension (falso) me ayudó
@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer
.setUseSuffixPatternMatch(false); // to use special character in path variables, for example, `[email protected]`
}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer
.favorPathExtension(false); // to avoid HttpMediaTypeNotAcceptableException on standalone tomcat
}
}
response.setHeader("Accept", "application/json");