90

this is my javascript:

    function getWeather() {
        $.getJSON('getTemperature/' + $('.data option:selected').val(), null, function(data) {
            alert('Success');                               
        });
    }

this is my controller:

@RequestMapping(value="/getTemperature/{id}", headers="Accept=*/*", method = RequestMethod.GET)
@ResponseBody
public Weather getTemparature(@PathVariable("id") Integer id){
    Weather weather = weatherService.getCurrentWeather(id);
        return weather;
}

spring-servlet.xml

<context:annotation-config />
<tx:annotation-driven />

Getting this error:

GET http://localhost:8080/web/getTemperature/2 406 (Not Acceptable)

Headers:

Response Headers

Server  Apache-Coyote/1.1
Content-Type    text/html;charset=utf-8
Content-Length  1070
Date    Sun, 18 Sep 2011 17:00:35 GMT

Request Headers

Host    localhost:8080
User-Agent  Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0.2) Gecko/20100101 Firefox/6.0.2
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
Connection  keep-alive
X-Requested-With    XMLHttpRequest
Referer http://localhost:8080/web/weather
Cookie  JSESSIONID=7D27FAC18050ED84B58DAFB0A51CB7E4

Interesting note:

I get 406 error, but the hibernate query works meanwhile. This is what tomcat log says, everytime when I change selection in dropbox:

 select weather0_.ID as ID0_0_, weather0_.CITY_ID as CITY2_0_0_, weather0_.DATE as DATE0_0_, weather0_.TEMP as TEMP0_0_ from WEATHER weather0_ where weather0_.ID=?

What could the problem be? There were two similar questions in SO before, I tried all the accepted hints there, but they did not work I guess...

Any suggestions? Feel free to ask questions...

Jaanus
  • 16,161
  • 49
  • 147
  • 202

26 Answers26

115

406 Not Acceptable

The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request.

So, your request accept header is application/json and your controller is not able to return that. This happens when the correct HTTPMessageConverter can not be found to satisfy the @ResponseBody annotated return value. HTTPMessageConverter are automatically registered when you use the <mvc:annotation-driven>, given certain 3-d party libraries in the classpath.

Either you don't have the correct Jackson library in your classpath, or you haven't used the <mvc:annotation-driven> directive.

I successfully replicated your scenario and it worked fine using these two libraries and no headers="Accept=*/*" directive.

  • jackson-core-asl-1.7.4.jar
  • jackson-mapper-asl-1.7.4.jar
Community
  • 1
  • 1
Villu Sepman
  • 1,294
  • 1
  • 8
  • 6
  • Nope, that was not the problem, check my answer. – Jaanus Sep 19 '11 at 11:16
  • If configuring HttpMessageConverters manually solved your problem, then using mvc:annotation-driven would do the same as it configures the converters and HandlerAdapters(HA) automatically. Note that if you configure any HA explicitly, it will cancel all other defaults. – Villu Sepman Sep 19 '11 at 11:37
  • Hmm, what is that `mvc` there? I used `` and tx is `xmlns:tx="http://www.springframework.org/schema/tx"` – Jaanus Sep 19 '11 at 11:58
  • xmlns:mvc="http://www.springframework.org/schema/mvc" (http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd) `Configures the annotation-driven Spring MVC Controller programming model.` – Villu Sepman Sep 19 '11 at 15:00
  • Getting this : `cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'mvc:annotation-driven'. ` – Jaanus Sep 19 '11 at 16:13
  • 1
    You got something like: ` ` and spring-web-3.0.x and spring-webmvc-3.0.x jars? – Villu Sepman Sep 19 '11 at 18:54
  • 1
    Ah I didn't have that schemalocation there..but thanks, this helped me. I thought that `tx:annotation-driven` is same as `mvc:annotation-drive` or smthin. – Jaanus Sep 19 '11 at 19:12
  • after adding mapper jar , it worked for me but what is the role of this jar file in this solution, please explain.. – VijayD Feb 25 '16 at 07:27
75

I had same issue, with Latest Spring 4.1.1 onwards you need to add following jars to pom.xml.

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

also make sure you have following jar:

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.13</version>
</dependency>

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>

406 Spring MVC Json, not acceptable according to the request "accept" headers

Community
  • 1
  • 1
AKB
  • 5,918
  • 10
  • 53
  • 90
  • This answer is the Maven aware version of the top answer, and it works prefectly! Maven exceptions could be more clear about what is actually going on under the hood. – Cotta Jun 08 '15 at 01:51
  • 4
    Can you provide where this is documented on Springs Official documentation ? How can someone know that this is the problem ? – Adelin Aug 18 '15 at 20:09
  • You only need to specify the dependencies to jackson-databind and jackson-mapper-asl, the other two are transitive dependencies and will be resolved anyway. – anre Sep 17 '15 at 19:21
  • 1
    This only worked for me after adding the second two dependencies. Thanks. – DocWatson Oct 30 '15 at 14:45
  • You definitely don't need both. Spring will add `MappingJacksonHttpMessageConverter` for Jackson 1 and `MappingJackson2HttpMessageConverter` for Jackson 2. Each of these is good enough to serialize/deserializing JSON. You only need one (go with Jackson 2 since it's more feature rich). – Sotirios Delimanolis Nov 23 '15 at 17:37
  • You don't want the second two dependencies - they're jackson 1. Try jackson-annotations instead. – JeeBee Jan 18 '16 at 11:39
  • With Spring 4.2.4 we use jackson versions 2.6.6 – Jarno Argillander Jul 21 '16 at 10:22
  • For me, I was just missing the jackson-databind artificat. – Grayson Aug 23 '16 at 18:09
  • adding the above 4 dependencies and in addition to that removing .htm from the request url resolved my issue : I am using spring 4.3.10 – Kevin Sebastian Fernandez Jun 03 '18 at 06:36
18

There is another case where this status will be returned: if the Jackson mapper cannot figure out how to serialize your bean. For example, if you have two accessor methods for the same boolean property, isFoo() and getFoo().

What's happening is that Spring's MappingJackson2HttpMessageConverter calls Jackson's StdSerializerProvider to see if it can convert your object. At the bottom of the call chain, StdSerializerProvider._createAndCacheUntypedSerializer throws a JsonMappingException with an informative message. However, this exception is swallowed by StdSerializerProvider._createAndCacheUntypedSerializer, which tells Spring that it can't convert the object. Having run out of converters, Spring reports that it's not being given an Accept header that it can use, which of course is bogus when you're giving it */*.

There is a bug for this behavior, but it was closed as "cannot reproduce": the method that's being called doesn't declare that it can throw, so swallowing exceptions is apparently an appropriate solution (yes, that was sarcasm). Unfortunately, Jackson doesn't have any logging ... and there are a lot of comments in the codebase wishing it did, so I suspect this isn't the only hidden gotcha.

kdgregory
  • 38,754
  • 10
  • 77
  • 102
  • Thank you so much! I'm new to Spring MVC and was having a really hard time figuring out how to return JSON. Everyone mentions missing @ResponseBody annotations and Jackson dependencies as the cause of 406 errors. In my case, it turns out I was just missing an accessor method for a public field belonging to the object I wanted to return as JSON. – Anthony Jack Sep 16 '13 at 19:48
  • Thanks @kdgregory! I forgot to add getter/setter for a field. Adding them fixed this issue. – Rubens Mariuzzo Apr 02 '15 at 03:31
16

I had the same problem, my controller method executes but response is Error 406. I debug AbstractMessageConverterMethodProcessor#writeWithMessageConverters and found that method ContentNegotiationManager#resolveMediaTypes always returns text/html which is not supported by MappingJacksonHttpMessageConverter. The problem is that the org.springframework.web.accept.ServletPathExtensionContentNegotiationStrategy works earlier than org.springframework.web.accept.HeaderContentNegotiationStrategy, and extension of my request /get-clients.html is the cause of my problem with Error 406. I just changed request url to /get-clients.

atott
  • 880
  • 10
  • 15
  • Hi atott, I have the same problem and your tip about changing the extension of the request solved my problem. Thanks a lot for sharing your solution!! – jherranzm Jun 15 '14 at 07:48
  • In my case it was a rest path id with an extension in it (in the test) that caused the 406 for the same reason, while the normal controller works (even if you were to use an extension in the rest path id). – Jur_ Feb 24 '19 at 14:16
12

Make sure that the sent object (Weather in this case) contains getter/setter

Riadh
  • 1,088
  • 2
  • 12
  • 25
9

Make sure that following 2 jar's are present in class path.

If any one or both are missing then this error will come.

jackson-core-asl-1.9.X.jar jackson-mapper-asl-1.9.X.jar
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Raju Rathi
  • 109
  • 1
  • 1
6

Finally found answer from here:

Mapping restful ajax requests to spring

I quote:

@RequestBody/@ResponseBody annotations don't use normal view resolvers, they use their own HttpMessageConverters. In order to use these annotations, you should configure these converters in AnnotationMethodHandlerAdapter, as described in the reference (you probably need MappingJacksonHttpMessageConverter).

Community
  • 1
  • 1
Jaanus
  • 16,161
  • 49
  • 147
  • 202
3

Check <mvc:annotation-driven /> in dispatcherservlet.xml , if not add it. And add

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.13</version>
</dependency>

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>

these dependencies in your pom.xml

SHIVA
  • 646
  • 1
  • 8
  • 13
3

Probably no one is scrolling down this far, but none of the above solutions fixed it for me, but making all my getter methods public did.

I'd left my getter visibility at package-private; Jackson decided it couldn't find them and blew up. (Using @JsonAutoDetect(getterVisibility=NON_PRIVATE) only partially fixed it.

Hazel T
  • 859
  • 1
  • 8
  • 22
  • That was exactly my issue. I change my setters from public to protected and Jackson stopped working. – juanmi Oct 17 '18 at 11:14
  • Same problem here, I was using `AbstractMap.SimpleImmutableEntry` then downgraded to `AbstractMap.SimpleEntry`, still no dice as it doesn't have a setter for the key. Gone pojo on this. – Robert Bain Mar 27 '20 at 22:41
2

I was having the same problem because I was missing the @EnableWebMvc annotation. (All of my spring configurations are annotation-based, the XML equivalent would be mvc:annotation-driven)

Anurag Sharma
  • 2,409
  • 2
  • 16
  • 34
jambriz
  • 1,273
  • 1
  • 10
  • 25
2
<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-base</artifactId>
    <version>2.6.3</version>
</dependency>
Rajan
  • 1,501
  • 4
  • 21
  • 37
  • 2
    While this code may answer the question, providing additional context regarding _how_ and/or _why_ it solves the problem would improve the answer's long-term value. – spongebob Oct 30 '15 at 17:01
1

As @atott mentioned.

If you have added the latest version of Jackson in your pom.xml, and with Spring 4.0 or newer, using @ResponseBody on your action method and @RequestMapping configured with produces="application/json;charset=utf-8", however, you still got 406(Not Acceptable), I guess you need to try this in your MVC DispatcherServlet context configuration:

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />

<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false" />
</bean>

That's the way how I resolved my issue finally.

Community
  • 1
  • 1
Raven
  • 426
  • 4
  • 7
1

check this thread. spring mvc restcontroller return json string p/s: you should add jack son mapping config to your WebMvcConfig class

@Override protected void configureMessageConverters( List<HttpMessageConverter<?>> converters) { // put the jackson converter to the front of the list so that application/json content-type strings will be treated as JSON converters.add(new MappingJackson2HttpMessageConverter()); // and probably needs a string converter too for text/plain content-type strings to be properly handled converters.add(new StringHttpMessageConverter()); }

Anh Lam
  • 122
  • 1
  • 1
  • 7
1

Spring 4.3.10: I used the below settings to resolve the issue.

Step 1: Add the below dependencies

    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.6.7</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.6.7</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.13</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>

Step 2: Add the below in your MVC DispatcherServlet context configuration:

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>

<bean id="contentNegotiationManager"
    class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false"/>
    <property name="favorParameter" value="true"/>
    <property name="ignoreAcceptHeader" value="false" />
</bean>

Since spring 3.2, as per the default configuration favorPathExtension is set as true, because of this if the request uri have any proper extensions like .htm spring will give priority for the extension. In step 2 I had added the contentNegotiationManager bean to override this.

1

In the controller, shouldn't the response body annotation be on the return type and not the method, like so :

@RequestMapping(value="/getTemperature/{id}", headers="Accept=*/*", method = RequestMethod.GET)
public @ResponseBody Weather getTemparature(@PathVariable("id") Integer id){
    Weather weather = weatherService.getCurrentWeather(id);
        return weather;
}

I'd also use the raw jquery.ajax function, and make sure contentType and dataType are being set correctly.

On a different note, I find the spring handling of json rather problematic. It was easier when I did it all myself using strings, and GSON.

NimChimpsky
  • 46,453
  • 60
  • 198
  • 311
  • The placement of `@ResponseBody` should not matter... I will look into GSON...but still would like this JSON to work if possible. – Jaanus Sep 18 '11 at 17:27
0

Other then the obvious problems I had another one that I couldn't fix regardless of including all possible JARs, dependancies and annotations in Spring servlet. Eventually I found that I have wrong file extension by that I mean I had two separate servlet running in same container and I needed to map to different file extensions where one was ".do" and the other as used for subscriptions was randomly named ".sub". All good but SUB is valid file extension normally used for films subtitle files and thus Tomcat was overriding the header and returning something like "text/x-dvd.sub..." so all was fine but the application was expecting JSON but getting Subtitles thus all I had to do is change the mapping in my web.xml file I've added:

<mime-mapping>
    <extension>sub</extension>
    <mime-type>application/json</mime-type>
</mime-mapping>
Alex Rashkov
  • 9,833
  • 3
  • 32
  • 58
0

I had the same problem unfortunately non of the solution here solved my problem as my problem was something in a different class.

I first checked that all dependencies are in place as suggested by @bekur then I checked the request/response that travels from clients to the server all headers was in place an properly set by Jquery. I then checked the RequestMappingHandlerAdapter MessageConverters and all 7 of them were in place, I really started to hate Spring ! I then updated to from Spring 4.0.6.RELEASE to 4.2.0.RELEASE I have got another response rather than the above. It was Request processing failed; nested exception is java.lang.IllegalArgumentException: No converter found for return value of type

Here is my controller method

  @RequestMapping(value = "/upload", method = RequestMethod.POST,produces = "application/json")
    public ResponseEntity<UploadPictureResult> pictureUpload(FirewalledRequest initialRequest) {

        DefaultMultipartHttpServletRequest request = (DefaultMultipartHttpServletRequest) initialRequest.getRequest();

        try {
            Iterator<String> iterator = request.getFileNames();

            while (iterator.hasNext()) {
                MultipartFile file = request.getFile(iterator.next());
                session.save(toImage(file));
            }
        } catch (Exception e) {
            return new ResponseEntity<UploadPictureResult>(new UploadPictureResult(),HttpStatus.INTERNAL_SERVER_ERROR);
        }
        return new ResponseEntity<UploadPictureResult>(new UploadPictureResult(), HttpStatus.OK);
    } 




    public class UploadPictureResult extends WebResponse{

    private List<Image> images;

    public void setImages(List<Image> images) {
        this.images = images;
    }
}






    public class WebResponse implements Serializable {


    protected String message;

    public WebResponse() {
    }

    public WebResponse(String message) {

        this.message = message;
    }


    public void setMessage(String message) {
        this.message = message;
    }
}

The solution was to make UploadPictureResult not to extend WebResponse

For some reason spring was not able to determine the how to convert UploadPictureReslt when it extended WebResponse

Adelin
  • 18,144
  • 26
  • 115
  • 175
0
<dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.8.0</version>
    </dependency>

i don't use ssl authentication and this jackson-databind contain jackson-core.jar and jackson-databind.jar, and then change the RequestMapping content like this:

@RequestMapping(value = "/id/{number}", produces = "application/json; charset=UTF-8", method = RequestMethod.GET)
public @ResponseBody Customer findCustomer(@PathVariable int number){
    Customer result = customerService.findById(number);
    return result;
}

attention: if your produces is not "application/json" type and i had not noticed this and got an 406 error, help this can help you out.

Crabime
  • 644
  • 11
  • 27
0

This is update answer for springVersion=5.0.3.RELEASE.

Those above answers will be only worked older springVersion < 4.1 version. for latest spring you have to add following dependencies in gradle file:

compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: fasterxmljackson
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: fasterxmljackson

fasterxmljackson=2.9.4

I hope this will be helpful for who using latest spring version.

0

make sure your have correct jackson version in your classpath

joyfun
  • 1
  • 1
0

Check as @joyfun did for the correct version of jackson but also check our headers ... Accept / may not be transmitted by the client ... use firebug or equivalent to check what your get request is actually sending. I think the headers attribute of the annotation /may/ be checking literals although I'm not 100% sure.

Dave G
  • 9,639
  • 36
  • 41
0

Simple answer just add Getter method in your domain/model class.

But Why this works ??

Under the hood Spring used HttpMessageConverters to convert your input JSON to Java Object.
The Accept header that is passed in the request is used to select appropriate MessageConvertor at runtime. These message convertors use getter of your domain/model class for conversion, so if there are no getter method, Marshall and unmarshall Java Objects to and from JSON will not happen, even if you add Jackson in your classpath, because even Jackson lib uses Getter methods for marshalling stuffs !!.

Jay Yadav
  • 236
  • 1
  • 2
  • 10
0

For people that are still facing 406 after adding ':*' to path variable regex.

Override below method of WebMvcConfigurer interface in any of @Configuration class.

@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.favorPathExtension(true)
            .mediaType("json", MediaType.APPLICATION_JSON)
            .mediaType("xml", MediaType.APPLICATION_XML)
            .mediaType("com", MediaType.APPLICATION_JSON);
}

I have added "com" as an extension as we were using email ids for path variable, and expected a application/json response from our application.

0

This helps me to resolve the issue.

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>

<bean id="contentNegotiationManager" 
 class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false"/>
    <property name="favorParameter" value="true"/>
    <property name="ignoreAcceptHeader" value="false" />
</bean>

However, note that <mvc:annotation-driven /> does not include the specific configuration you had in your original snippet for content negotiation. So if you only include <mvc:annotation-driven /> and omit the contentNegotiationManager bean configuration, the application will use the default behavior for content negotiation. The default behavior typically includes considering the Accept header and, if available, the file extension in the URL to determine the media type of the response.

helvete
  • 2,455
  • 13
  • 33
  • 37
unbuntry
  • 11
  • 2
0

in spring boot: imagine that we want to return in web service method same as :

ResponseEntity.status(HttpStatus.CREATED)
                    .body(myObject);
myObject class **need to** use @Data annotation from lombok pakage

@Data
public class myClass{
...
}
Procrastinator
  • 2,526
  • 30
  • 27
  • 36
Mojtaba
  • 39
  • 3
-4

Can you remove the headers element in @RequestMapping and try..

Like


@RequestMapping(value="/getTemperature/{id}", method = RequestMethod.GET)

I guess spring does an 'contains check' rather than exact match for accept headers. But still, worth a try to remove the headers element and check.

stratwine
  • 3,663
  • 2
  • 26
  • 32
  • I removed, but still error. Btw when I look tomcat log, then then query with this was `weatherService.getCurrentWeather(id);` "activated"...so something works...is it possible that 406 appears and Hibernate SQL select works in the same time? – Jaanus Sep 18 '11 at 18:56
  • Please try this one it should work. Add this annotation on controller @RequestMapping(method = RequestMethod.GET,headers = {"Accept=text/xml, application/json"}) – sats Mar 28 '16 at 19:41