java - headers - Spring MVC+JSON=406 No aceptable
http request headers list (19)
Intento generar una respuesta JSON simple trabajando. En este momento recibo el error 406 No aceptable. Tomcat dice: "El recurso identificado por esta solicitud solo es capaz de generar respuestas con características no aceptables de acuerdo con los encabezados de" aceptación "de la solicitud". aunque mis encabezados Accept
son
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
En tomcat / lib tengo todos los jar Tomcat, Spring jars y jackson-all-1.9.0.jar. Estoy usando Spring 3.2.2 con Tomcat 7.
Soy consciente de que este tema se ha debatido muchas veces, pero ninguna de las soluciones me funciona.
web.xml
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring Web MVC Application</display-name>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
</web-app>
dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<context:component-scan base-package="com.smiechmateusz.controller" />
<context:annotation-config />
<mvc:annotation-driven />
</beans>
HelloWorldController.java
package com.smiechmateusz.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
import com.smiechmateusz.dao.Foo;
@Controller
@RequestMapping("/")
public class HelloWorldController extends AbstractController{
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
ModelAndView model = new ModelAndView("HelloWorldPage");
return model;
}
@RequestMapping(value="foobar.htm", method = RequestMethod.GET)
public @ResponseBody Foo getShopInJSON() {
Foo f = new Foo();
f.setX(1);
f.setY(2);
f.setDescription("desc");
return f;
}
}
Foo.java
package com.smiechmateusz.dao;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="foobaz")
public class Foo implements Serializable
{
private int x, y;
String description;
int id;
@Column(name = "x")
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
@Column(name = "y")
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Column(name = "description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Id @GeneratedValue
@Column(name = "id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Ya he intentado agregar
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonConverter"/>
</list>
</property>
</bean>
a mi dispatcher-servlet.xml o cambiando jakcson-all a jackson-asl y jackson-core-asl, pero la salida fue la misma.
Aceptar: texto / html, application / xhtml + xml, application / xml; q = 0.9, / ; q = 0.8
Ese debería ser el problema. JSON se sirve como application/json
. Si configura el encabezado Aceptar en consecuencia, debe obtener la respuesta adecuada. (Hay complementos de navegador que te permiten configurar encabezados, me gusta más "Poster" para Firefox)
Con Spring 4 solo agrega @EnableWebMvc
, por ejemplo:
@Controller
@EnableWebMvc
@RequestMapping(value = "/articles/action", headers="Accept=*/*", produces="application/json")
public class ArticlesController {
}
Debe registrar el enlace de anotación para Jackson en su spring-mvc-config.xml, por ejemplo:
<!-- activates annotation driven binding -->
<mvc:annotation-driven ignoreDefaultModelOnRedirect="true" validator="validator">
<mvc:message-converters>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
Luego, en su controlador puede usar:
@RequestMapping(value = "/your_url", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
Hay otro caso en el que se devolverá este estado: si el mapeador de Jackson no puede descifrar cómo serializar su frijol. Por ejemplo, si tiene dos métodos de acceso para la misma propiedad booleana, isFoo()
y getFoo()
.
eliminado getFoo()
y puesto isFoo()
. funcionó para mí.
Hoy también he pasado por el mismo problema. En mi caso, en web.xml
tengo
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
mi URL tiene extensión .html
. Ej .: .../getUsers.html
. Pero estoy devolviendo datos JSON en el controlador. La extensión .html establecerá de forma predeterminada accept type como html.
Entonces cambié a lo siguiente:
web.xml:
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.html</url-pattern>
<url-pattern>*.json</url-pattern>
</servlet-mapping>
URL:
.../getUsers.json
Todo está funcionando bien ahora. Espero eso ayude.
Mi clase se anotó con JsonSerialize, y el parámetro de inclusión se estableció en JsonSerialize.Inclusion.NON_DEFAULT
. Esto hizo que Jackson determinara los valores por defecto para cada propiedad de bean. Tenía una propiedad de frijol que me devolvió un int. El problema en mi caso era que Bean getter llamaba a un método que tiene un tipo de devolución inferida (es decir, un método genérico). Por alguna extraña razón este código compilado; no debería haberse compilado porque no puede usar un int para un tipo de retorno inferido. Cambié el ''int'' a un ''Entero'' para esa propiedad de frijol y ya no obtuve un 406. Lo curioso es que ahora el código no se puede compilar si cambio el Entero de nuevo a un int.
Mi valor RequestMapping
terminaba con .html, que debería ser algo diferente.
Intenté cambiarlo a .json y funcionó para mí.
Ninguna de las otras respuestas me ayudó.
Leí docenas de respuestas de acerca de 406 No aceptable, HttpMediaTypeNotAcceptableException, archivo de varias partes, ResponseBody, estableciendo Accept headers, produce, consume etc.
Tuvimos Spring 4.2.4 con SpringBoot y Jackson configurados en build.gradle:
compile "com.fasterxml.jackson.core:jackson-core:2.6.7"
compile "com.fasterxml.jackson.core:jackson-databind:2.6.7"
Todas las rutas funcionaron bien en nuestros otros controladores y pudimos usar GET, POST, PUT y DELETE. Luego comencé a agregar la capacidad de carga de archivos de varias partes y creé un nuevo controlador. Las rutas GET funcionan bien pero nuestro POST y DELETE no. No importa cómo intenté diferentes soluciones desde aquí en SO, seguí recibiendo 406 No aceptable.
Entonces, finalmente, tropecé con esta respuesta SO: Spring throwing HttpMediaTypeNotAcceptableException: no se pudo encontrar una representación aceptable debido al punto en la ruta url
Lea la respuesta de Raniz y todos los comentarios.
Todo se reducía a nuestros valores de @RequestMapping:
@RequestMapping(value = "/audio/{fileName:.+}", method = RequestMethod.POST, consumes="multipart/*")
public AudioFileDto insertAudio(@PathVariable String fileName, @RequestParam("audiofile") MultipartFile audiofile) {
return audioService.insert(fileName, audiofile);
}
@RequestMapping(value = "/audio/{fileName:.+}", method = RequestMethod.DELETE)
public Boolean deleteAudio(@PathVariable String fileName) {
return audioService.remove(fileName);
}
La parte {fileName:.+}
En un valor @RequestMapping provocó que el 406 no sea aceptable en nuestro caso.
Aquí está el código que agregué de la respuesta de Raniz:
@Configuration
public class ContentNegotiationConfig extends WebMvcConfigurerAdapter {
@Override
void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
// Turn off suffix-based content negotiation
configurer.favorPathExtension(false);
}
}
EDITAR 29 de agosto de 2016:
Nos metimos en problemas al usar configurer.favorPathExtension(false)
: las imágenes SVG estáticas dejaron de cargarse. Después del análisis, encontramos que Spring comenzó a enviar archivos SVG a la interfaz de usuario con el tipo de contenido "application / octet-stream" en lugar de "image / svg + xml". Solucionamos esto enviando fileName como un parámetro de consulta, como:
@RequestMapping(value = "/audio", method = RequestMethod.DELETE)
public Boolean deleteAudio(@RequestParam String fileName) {
return audioService.remove(fileName);
}
También eliminamos el configurer.favorPathExtension(false)
. Otra forma podría ser codificar fileName en la ruta, pero elegimos el método de parámetro de consulta para evitar otros efectos secundarios.
No pude verlo como una respuesta aquí, así que pensé en mencionar que recibí este error usando la primavera 4.2 cuando accidentalmente eliminé el getter / setter de la clase que esperaba que se me devolviera como Json.
Parece que estás tratando de producir / recibir la salida json. Veo dos problemas con su enfoque. 1) No especificó la aplicación / json en el encabezado Aceptar 2) Debe especificar produce = "aplicación / json" en su @RequestMapping
Prueba agregar
@RequestMapping(method = RequestMethod.GET,headers = {"Accept=text/xml, application/json"})
en getShopInJSON()
.
Funcionó para mí
Si está usando Maven y el último código de Jackson , puede eliminar toda la configuración específica de Jackson de sus archivos XML de configuración de primavera (todavía necesitará una etiqueta accionada por anotación <mvc: annotation-driven />) y simplemente agregar algunas dependencias de Jackson a su archivo pom.xml. Vea a continuación un ejemplo de las dependencias. Esto funcionó para mí y estoy usando:
- Apache Maven 3.0.4 (r1232337; 2012-01-17 01: 44: 56-0700)
- org.springframework versión 3.1.2.RELEASE
spring-security versión 3.1.0.RELEASE.
...<dependencies> ... <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.2.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.2.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.2.3</version> </dependency> ... </dependencies>...
Supongo que el problema estaba en el uso de la extensión * .htm en RequestMapping ( foobar.htm ). Intenta cambiarlo a footer.json u otra cosa.
El enlace a la respuesta correcta: https://.com/a/21236862/537246
PD
Es en Spring lo que hace algo por defecto, concerniente a que los desarrolladores conozcan toda la API de Spring de la A a la Z. Y luego simplemente "406 no es aceptable" sin ningún detalle, ¡y los registros de Tomcat están vacíos!
Tal vez todos los campos de tu POJO necesitan Getter y Setter.
Lo arreglé de acuerdo con este problema. referencia: Spring MVC - HttpMediaTypeNotAcceptableException
Y 406 no es un mensaje útil para arreglar el error. Debes depurar los códigos y ver cuál es la Excepción en la tierra.
Tengo el problema similar y lo resuelvo usando el código siguiente
public class ProductList {
private List<Product> productList = new ArrayList<Product>();
@JsonProperty("data")
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT)
public List<Product> getProductList() {
return productList;
}
public void setProductList(List<Product> productList) {
this.productList = productList;
}
I am setting ProductList object in ResponseEntity object and returning from controller.
Una forma más de obtener este error es crear una clase sin miembros públicos. 406 inaceptable es un mensaje de error bastante inútil en este escenario.
Use la dependencia a continuación en su pom
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>
Vea el problema es con la extensión. Dependiendo de la extensión, Spring podría deducir el tipo de contenido. Si su url finaliza con .com , envía texto / html como encabezado de tipo de contenido. Si desea cambiar este comportamiento de Spring, utilice el siguiente código:
@Configuration
@Import(HibernateConfig.class)
@EnableWebMvc
// @EnableAsync()
// @EnableAspectJAutoProxy
@ComponentScan(basePackages = "com.azim.web.service.*", basePackageClasses = { WebSecurityConfig.class }, excludeFilters = { @ComponentScan.Filter(Configuration.class) })
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false).favorParameter(true).parameterName("mediaType").ignoreAcceptHeader(true).useJaf(false)
.defaultContentType(MediaType.APPLICATION_JSON).mediaType("xml", MediaType.APPLICATION_XML).mediaType("json", MediaType.APPLICATION_JSON);
}
@Bean(name = "validator")
public Validator validator() {
return new LocalValidatorFactoryBean();
}
}
Aquí, estamos estableciendo favorPathExtension en falso y Default Content-type en Application / json. Nota: La clase HibernateConfig contiene todos los beans.
esto es porque el objeto no es aceptable en jsp ... usa su
agrega esta dependencia o cualquier otra cadena json convertida a jsp ...
por ejemplo agregar esto en pom
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.6.2</version>
</dependency>
y usa un código como ese:
@RequestMapping(value="foobar.htm", method = RequestMethod.GET)
public @ResponseBody String getShopInJSON() {
Foo f = new Foo();
f.setX(1);
f.setY(2);
f.setDescription("desc");
return new Gson().toJson(f); //converted object into json string
}//return converted json string