Spring 3.x JSON status 406 "characteristics not acceptable according to the request "accept" headers ()"
Asked Answered
S

14

44

Upon trying to get my response in JSON using Spring 3.x, I get the 406 error "The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers ()."

Here is my environment

* Spring 3.2.0.RELEASE
* included jackson-mapper-asl-1.7.9.jar, jackson-core-asl-1.7.9.jar
* Tomcat 6.x
* mvc:annotation-driven in Spring configuration XML file

My Controller:

@RequestMapping("/contest")
public class ContestController {

    @RequestMapping(value="{name}", headers="Accept=*/*", method = RequestMethod.GET)
    public @ResponseBody Contest getContestInJSON(@PathVariable String name) {
        Contest contest = new Contest();
        contest.setName(name);
        contest.setStaffName(new String("contestitem1"));

        return contest;
    }

}

My Spring Configuration file

<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-3.0.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">

<context:component-scan base-package="com.contestframework.controllers" />

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">

<property name="mediaTypes">
    <map>
      <entry key="atom" value="application/atom+xml"/>
      <entry key="html" value="text/html"/>
      <entry key="json" value="application/json"/>
    </map>
 </property>

 <property name="viewResolvers">
 <list>
  <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/pages/"/>
    <property name="suffix" value=".jsp"/>
  </bean>
 </list>
 </property>

 <property name="defaultViews">
  <list>
   <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
  </list>
 </property>

 </bean>

<mvc:annotation-driven />

</beans>

After this I just access the Controller using below:

http://domain/SpringWebProject/json/contest/abcd

and the response I get is Status 406: "The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers ()."

I also tried an alternate mechanism by access this using Javascript AJAX to make sure my request header has application/JSON but this led to the same Status 406 result

$.getJSON('contest/abcd', function(data) {
console.log(data) }

Here is my REQUEST HEADER captured from browser:

Request URL:http://localhost:8080/SpringWebProject/json/contest/abcd
Request Method:GET
Status Code:406 Not Acceptable

Accept:application/json, text/javascript, */*; q=0.01
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Cookie:JSESSIONID=59689C95B0B9C21494EB0AB9D9F7BCCD
Host:localhost:8080
Referer:http://localhost:8080/SpringWebProject/json/welcome
User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4
X-Requested-With:XMLHttpRequest
Response Headersview source
Content-Length:1070
Content-Type:text/html;charset=utf-8
Date:Fri, 12 Oct 2012 18:23:40 GMT
Server:Apache-Coyote/1.1

Appreciate any help in this regard.

Sidewheel answered 12/10, 2012 at 18:33 Comment(0)
U
20

There is nothing wrong in your configuration, let me suggest a few small changes though:

a) Your namespaces appear wrong - they are referring to the 3.0 schemas, just change them to either 3.1 one's or don't refer to the version explicitly, this way for eg.

xsi:schemaLocation="
    http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans.xsd

OR

xsi:schemaLocation="
    http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

b) You don't require the ContentNegotiatingViewResolver, you can remove everything but the component-scan and <mvc:annotation-driven/> from your configuration

c) The request will not directly work from the browser as it explicitly requires an Accept header of "application/json" - $.getJson call should work though as it sends the correct headers

d) Remove the headers=Acc.. from the @RequestMapping, and produces also, both are filtering criteria to match up the correct mapped method call.

With these, there is no reason why the json should not get served out, can you please try with these and see how it goes.

Unpracticed answered 13/10, 2012 at 12:37 Comment(7)
I tried all that you had suggested and also removed version references. No difference though :( here is the mapping information at start up and my JSON request is same as before INFO: Mapped "{[/contest/{name}],methods=[GET],params=[],headers=[],consumes=[],produces= [],custom=[]}" onto public com.contestframework.model.Contest com.contestframework.controllers.ContestController.getContestInJSON(java.lang.String) If you find time, I could send you my exported eclipse project also. Because at this point I am running out of ideas.Sidewheel
Yes, if you can create a project and place it on github, I can try to fix it and send you a pull request.Unpracticed
Thanks - I have provisioned github to your gmail addressSidewheel
The issue with your project was actually very small - you have protected getters in your Contest class, just change it to public methods and it should just work cleanly.Unpracticed
I have sent you a github pull request also with the fix.Unpracticed
Thanks a Ton. This indeed resolved the problem. Does Spring suppress errors like these? I am assuming the Jackson libraries did not like the fact that these methods were protected BUT did not show any warnings, errors. Thanks again ..this issue had been holding up the whole architecture.Sidewheel
Can you send me the solution structure, I am facing the same issue.Unmoral
C
49

I have also just experienced this same issue. It would appear it is an issue with the latest 3.2.0.RELEASE, as I previously had 3.1.2.RELEASE and it all worked. After changing to 3.2.0.RELEASE it breaks. Have tested with 3.1.3.RELEASE and that works fine. So for now I would suggest rolling back to 3.1.3.RELEASE

EDIT: Thanks to another post on this site that linked to the following location: http://static.springsource.org/spring-framework/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-config-content-negotiation

I've now got it working by disabling the getting of media type based on the extension of the requested path. This can be done by the following:

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <!-- Turn off working out content type based on URL file extension, should fall back to looking at the Accept headers -->
    <property name="favorPathExtension" value="false" />
</bean>

And specify version 3.2 for all the xsd schema locations.

And this is using the following jackson jars:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.1.2</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.1.2</version>
</dependency>
Catapult answered 18/12, 2012 at 18:35 Comment(2)
This is exactly the case with my application. Thanks a ton! I feel like I need to give up 10 times. I have been fruitelessly searching for this issue. This worked like magic.Series
Only jackson-databind was need in my app.Pinxit
U
20

There is nothing wrong in your configuration, let me suggest a few small changes though:

a) Your namespaces appear wrong - they are referring to the 3.0 schemas, just change them to either 3.1 one's or don't refer to the version explicitly, this way for eg.

xsi:schemaLocation="
    http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans.xsd

OR

xsi:schemaLocation="
    http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

b) You don't require the ContentNegotiatingViewResolver, you can remove everything but the component-scan and <mvc:annotation-driven/> from your configuration

c) The request will not directly work from the browser as it explicitly requires an Accept header of "application/json" - $.getJson call should work though as it sends the correct headers

d) Remove the headers=Acc.. from the @RequestMapping, and produces also, both are filtering criteria to match up the correct mapped method call.

With these, there is no reason why the json should not get served out, can you please try with these and see how it goes.

Unpracticed answered 13/10, 2012 at 12:37 Comment(7)
I tried all that you had suggested and also removed version references. No difference though :( here is the mapping information at start up and my JSON request is same as before INFO: Mapped "{[/contest/{name}],methods=[GET],params=[],headers=[],consumes=[],produces= [],custom=[]}" onto public com.contestframework.model.Contest com.contestframework.controllers.ContestController.getContestInJSON(java.lang.String) If you find time, I could send you my exported eclipse project also. Because at this point I am running out of ideas.Sidewheel
Yes, if you can create a project and place it on github, I can try to fix it and send you a pull request.Unpracticed
Thanks - I have provisioned github to your gmail addressSidewheel
The issue with your project was actually very small - you have protected getters in your Contest class, just change it to public methods and it should just work cleanly.Unpracticed
I have sent you a github pull request also with the fix.Unpracticed
Thanks a Ton. This indeed resolved the problem. Does Spring suppress errors like these? I am assuming the Jackson libraries did not like the fact that these methods were protected BUT did not show any warnings, errors. Thanks again ..this issue had been holding up the whole architecture.Sidewheel
Can you send me the solution structure, I am facing the same issue.Unmoral
I
11

I had the same problem and I solved it by adding following dependency

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>${jackson.version}</version>
</dependency>

Previously I'm doing it with following dependency

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>${com.jackson.core-version}</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>${com.jackson.core-version}</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${com.jackson.core-version}</version>
</dependency>

In short I have replace com.fasterxml.jackson.core by org.codehaus.jackson

Ischia answered 22/12, 2013 at 6:46 Comment(1)
Adding dependency for jackson-mapper-asl worked for me.Cleodell
H
8

I had this problem in Spring MVC 4. Adding jackson-annotations, jackson-core and jackson-databind didn't solve the problem. Try this libs:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.1.2</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.1.2</version>
</dependency>
<dependency>
  <groupId>org.codehaus.jackson</groupId>
  <artifactId>jackson-mapper-asl</artifactId>
  <version>1.9.13</version>
</dependency>
Hy answered 29/8, 2014 at 20:10 Comment(1)
You nailed it for me, Weslei! I was having this MVC 4. No other solution worked. Thanks a million for saving my day!Trilobite
Z
7

I had the same problem and the comment added by Biju Kunjummen in this answer worked for me perfectly

https://mcmap.net/q/369905/-spring-3-x-json-status-406-quot-characteristics-not-acceptable-according-to-the-request-quot-accept-quot-headers-quot

That is have public getters in my Java class

Ziegfeld answered 12/10, 2012 at 18:34 Comment(0)
I
7

I think you need to add a produces="application/json" to your @RequestMapping (haven't looked at spring mvc in a while so i'm not 100% positive) ...

http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html

16.3.2.6 Producible Media Types

You can narrow the primary mapping by specifying a list of producible media types. The request will be matched only if the Accept request header matches one of these values. Furthermore, use of the produces condition ensures the actual content type used to generate the response respects the media types specified in the produces condition. For example:

@Controller
@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, produces="application/json")
@ResponseBody
public Pet getPet(@PathVariable String petId, Model model) {    
    // implementation omitted
}
Iridize answered 12/10, 2012 at 18:50 Comment(2)
I just tried that after reading your comment. It gives back the same result status 406. Confirmed the same when server starts the mapping is done correctly with produces option -- INFO: Mapped "{[/contest/{name}],methods=[GET],params=[],headers=[],consumes=[],produces=[application/json || */*],custom=[]}" onto public com.contestframework.model.Contest com.contestframework.controllers.ContestController.getContestInJSON(java.lang.String)Sidewheel
@les2, that worked!! I have struggling with the problem, tried adding HttpServletResponse and set content type to "application/json", it wouldn't resolve. 'produces' attribute worked for me.Illimani
B
6

I had a similar problem, it got resolved when I added jackson-databind library.

These are my dependencies:

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.12</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.4.3</version>
</dependency>
Bestow answered 12/12, 2014 at 16:19 Comment(1)
I am glad it helped! In my recent projects I started to use spring boot, no worries for versions or dependencies! ;)Bestow
S
4

Thank you for sharing you experience.I experienced the same problem and it works for me using configuration as show below:

  1. Spring MVC Version : 3.2.5.RELEASE
  2. Apache-tomcat-6.0.24
  3. JDK1.6
  4. jackson-core-asl-1.9.10.jar
  5. jackson-mapper-asl-1.9.10.jar

Spring MVC Config File:

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<!-- Turn off working out content type based on URL file extension, should fall back to looking at the Accept headers -->
    <property name="favorPathExtension" value="false" />
</bean>

Model class : Country.java

 private Integer countryId;
 private String name;
 //public setters and getters

Controller Method:

@RequestMapping(value = "/get_country_json",method = RequestMethod.GET)
@ResponseBody
public Country getCountry()

Deployment Descriptor(web.xml)

 <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>

URL Requested to call controller method: /SpringCURDApp/get_country_json.htm

I hope this can help someone.

Supply answered 12/10, 2012 at 18:34 Comment(0)
O
4

Don't make the same mistake I did, spend all day playing around with Spring configuration, when actually your object returned in a web service is not marshaling to XML correctly. It seems Spring catches a JAXB marshaling error and doesn't report it. Use this sandbox code to validate JAXB marshaling:

MyClass myclass = new MyClass();
//populate myclass here

JAXBContext context = JAXBContext.newInstance(MyClass.class);

Marshaller m = context.createMarshaller();
StringWriter w = new StringWriter();

m.marshal(myclass, w);
System.out.println(w);

This produced and displayed an exception. Fixed the cause, and my web service is available in both XML and JSON.

Overmaster answered 5/9, 2014 at 17:59 Comment(0)
E
3

Shortly:

For Spring MVC 4.1.6 there is enough:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.5.0</version>
</dependency>

jackson-databind has dependency on core and annotations artifacts.


In details:

What is HTTP 406 error?

406 Not Acceptable The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request.

It means that Server cannot generate content which MEDIA TYPE stated in Accept Header.

But how does server know which MEDIA TYPE it can generate and which not?

Spring Web has concept of HttpMessageConverter. Some of these converters are already registered in Spring and AbstractMessageConverterMethodArgumentResolver holds them in property messageConverters.

During request processing AbstractMessageConverterMethodProcessor analyzes what spring can convert and saves all supported MEDIA TYPES in producibleMediaTypes variable. If requested MEDIA TYPE is not producible then says Error 406 == I cannot generated requested media type. Sorry.

To cut the long story short - register required converters. In your case it's jackson library which produces application/json

Enucleate answered 10/6, 2015 at 21:36 Comment(0)
A
0

Please, see http://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-config-content-negotiation As you can see

"For file extensions in the request URI, the MVC Java config and the MVC namespace, automatically register extensions such as .json, .xml, .rss, and .atom if the corresponding dependencies such as Jackson, JAXB2, or Rome are present on the classpath."

You should add ".json" at the end of URI (like http://domain/SpringWebProject/json/contest/abcd.json) It works for me.

Apologete answered 7/6, 2015 at 7:23 Comment(0)
T
0

I had similar issue but it was weird. I will explain how I resolved it.

In my web.xml my dispacher servlet was mapped to *.htm

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

and no matter what I did it always threw -

The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" header

Finally I changed it to

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

and it worked. What I think is when you just specify

<mvc:annotation-driven/> 

the extension takes precedence over accept header and .htm was was creating issues. And obviously I could not use xml or json since servlet itself was not mapped.

I would also like to add that produces annotation that you, spring will try to map it will accept header of the incoming request. I was making request handler method generic for json and xml. Since I am using Java 8 and Jaxb is inbuilt in Java since Java 7 no need for JAXB dependency. For json I only needed to add -

<dependency org="com.fasterxml.jackson.core" name="jackson-databind" rev="2.8.5"/>

I am using ivy for dependency management.

Trelu answered 14/1, 2017 at 15:55 Comment(0)
D
0

Maybe you should update your jackson library. I use Spring v4.3.8 and I use it as follows:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.8.7</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.8.7</version>
</dependency>
Demimonde answered 5/6, 2017 at 8:46 Comment(0)
D
-1

If you are using Spring 4 then you must only update your libraries:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.3.0</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.3.0</version>
    </dependency>
Desrosiers answered 30/5, 2015 at 6:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.