Spring MVC - HttpMediaTypeNotAcceptableException
Asked Answered
I

15

48

I keep getting this HttpMediaTypeNotAcceptableException error for AJAX requests when using with Spring MVC and JSON.. full stack trace of the error is..

 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)

little googling I did shows that the request should contain something like "accept: application/json" which is does have.. here is the request headers from 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

Now I am completely lost at what is happening here.. what else can go wrong here to get thi error...

Italicize answered 25/8, 2011 at 21:14 Comment(2)
Please post your controller code and dispatcher servlet Spring context file(s). I am guessing you don't have a proper message converter configured for JSON (e.g. MappingJacksonHttpMessageConverter).Singlephase
https://mcmap.net/q/245277/-spring-changing-media-type-on-uri-with-au-at-the-endArchibald
M
51

Please make sure that you have the following in your Spring xml file:

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

and all items of your POJO should have getters/setters. Hope it helps

Middleton answered 25/8, 2011 at 21:35 Comment(7)
Getters were missing from my result objectIngoing
Don't forget to refer this - #22385222Danaus
Since Spring 4+ you just need to add <context:annotation-config/>, no extra beans required for working with JSON anymore.Bettor
How could you do this configuration without doing it in the Spring xml file? I'm not using that file currently. Couldn't I autowire this or something?Orella
I am using Spring 4.x and just using <context:annotation-config/> does not work.Cicelycicenia
This is old answer. For Spring 4 and above <mvc:annotation-driven/> will work. Make sure you have correct jackson version in spring 4 #21854869Gallican
Getter/Setters not needed anymore, you can use public fields for DTOs.Controversy
A
26

From: http://georgovassilis.blogspot.ca/2015/10/spring-mvc-rest-controller-says-406.html

You've got this Spring @RestController and mapped a URL that contains an email as part of the URL path. You cunningly worked around the dot truncation issue [1] and you are ready to roll. And suddenly, on some URLs, Spring will return a 406 [2] which says that the browser requested a certain content type and Spring can't serialize the response to that content type. The point is, you've been doing Spring applications for years and you did all the MVC declarations right and you included Jackson and basically you are stuck. Even worse, it will spit that error out only on some emails in the URL path, most notably those ending in a ".com" domain.

@RequestMapping(value = "/agenda/{email:.+}", method = RequestMethod.GET)
public List<AgendaEntryDTO> checkAgenda(@PathVariable("email") String email)

The issue [3] is quite tricky: the application server performs some content negotiation and convinces Spring that the browser requested a "application/x-msdownload" content, despite that occurring nowhere in the request the browser actually submitted.

The solution is to specify a content negotiation manager for the web application context:

<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>
Annadiana answered 25/1, 2016 at 22:31 Comment(0)
D
19

Make sure you add both Jackson jars to classpath:

  • jackson-core-asl-x.jar
  • jackson-mapper-asl-x.jar

Also, you must have the following in your Spring xml file:

<mvc:annotation-driven />
Doorsill answered 27/12, 2011 at 15:15 Comment(2)
This isn't true for spring4.x. In my case, all I needed was getters and setters.Serval
@Serval Your comment helped me more than all the other answers combined! I faced a similar problem, and adding getters and setters helped me too. Spring Boot version 3+Scrawly
J
13

Because this is the first google hit for "HttpMediaTypeNotAcceptableException" I like to add another problem that I've stumbled upon which resulted in HttpMediaTypeNotAcceptableException too.

In my case it was a controller that specified "produces", e.g.:

@RequestMapping(path = "/mypath/{filename}", method = RequestMethod.GET,
        produces = { MediaType.APPLICATION_XML_VALUE }

because I wanted to serve an XML file. At the same time I'm using a class with "@ControllerAdvice" to catch Exceptions, e.g. if the requested file wasn't found. The Exception handler was returning JSON so the client (angular) app could display the error message somewhere in the SPA.

Now the controller wanted to return XML but the Exception Handler was returning JSON so the HttpMediaTypeNotAcceptableException was raised. I solved this by adding JSON as possible "produces" value:

produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}

Hope this helps somebody else. :-)

Jenaejenda answered 24/3, 2017 at 10:33 Comment(0)
K
11

Just something important to keep in mind: Spring versions prior to 3.1.2 are compatible with JACKSON 1.x and NOT with JACKSON 2.x. This is because going from JACKSON 1.x to 2.x the classes's package names were changed. In JACKSON 1.x classes are under org.codehaus.jackson while in JACKSON 2.x they are under com.fasterxml.jackson.

To address this issue, starting with Spring 3.1.2 they added a new MappingJackson2HttpMessageConverter to replace MappingJacksonHttpMessageConverter.

You could find more details regarding compatibility issues in this link: Jackson annotations being ignored in Spring

Kappenne answered 1/5, 2013 at 21:8 Comment(0)
F
8

in my case favorPathExtension(false) helped me

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

}

Fendley answered 12/12, 2017 at 12:2 Comment(2)
SO is such an awesome place. After struggling with HttpMediaTypeNotAcceptableException for hours, I came across this wonderful answer and resolved my issue +100Natalianatalie
Since Spring 5.3 the default for both properties is false and both have been deprecated. For more details see the javadoc for PathMatchConfigurer and ContentNegotiationConfigurerNissa
B
5

In your Spring @Configuration class which extends WebMvcConfigurerAdapter override the method configureMessageConverters, for instance:

@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");

}

And the error will be gone.

Bayou answered 11/5, 2015 at 7:59 Comment(0)
S
2

I had the same issue, but i had figured out that basically what happens when spring is trying to render the response it will try to serialize it according to the media type you have specified and by using getter and setter methods in your class

before my class used to look like below

public class MyRestResponse{
    private String message;
}

solution looks like below

public class MyRestResponse{
    private String message;
    public void setMessage(String msg){
        this.message = msg;
    }
    public String getMessage(){
        return this.message;
    }
}

that's how it worked for me

Sob answered 9/5, 2017 at 10:57 Comment(0)
C
1
response.setHeader("Accept",  "application/json");
Crunode answered 13/1, 2013 at 10:18 Comment(0)
F
1

Try to add "jackson-databind" jars to pom.xml

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

And produces ={MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE} to @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},...

Freebooter answered 8/2, 2018 at 9:51 Comment(0)
O
0

As Alex hinted in one of the answers, you could use the ContentNegotiationManagerFactoryBean to set the default content-type to "application/json", but I felt that that approach was not for me.

What I was trying to do was to post a form to a method like this

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

What I instead chose to do was to change the "Accept" header of the request from the browser to "application/json", thereby making SpringMVC find my method.

Using the (not yet finalized) Javascript Fetch API:

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à! Now SpringMVC finds the method, validates the form, and lets you return a JSON POJO.

Ofilia answered 2/7, 2016 at 17:9 Comment(0)
T
0

In my case, just add @ResponseBody annotation to solve this issue.

Twine answered 27/7, 2017 at 7:32 Comment(0)
C
0

In my case

 {"timestamp":1537542856089,"status":406,"error":"Not Acceptable","exception":"org.springframework.web.HttpMediaTypeNotAcceptableException","message":"Could not find acceptable representation","path":"/a/101.xml"}

was caused by:

path = "/path/{VariableName}" but I was passing in VariableName with a suffix, like "abc.xml" which makes it interpret the .xml as some kind of format request instead. See answers there.

Cathedral answered 20/9, 2018 at 22:15 Comment(0)
T
0

For me the problem was the URL I was trying to access. I had url like this:

{{ip}}:{{port}}/{{path}}/person.html

When you end url with .html it means that you will not accept any other payload than html. I needed to remove .html from the end for my endpoint to work properly. (You can also append .json at the end of url and it will work too)

Additionally your url-pattern in web.xml need to be configured properly to allow you to access the resource. For me it is

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

Previously I had *.html* and it was preventing me an access to the endpoint.

Taproom answered 6/7, 2019 at 19:7 Comment(0)
W
0

More of a comment than an answer...

I'm using Lombok and I was developing a (very) skeleton API and my response DTO didn't have any fields (yet) and I got the HttpMediaTypeNotAcceptableException error while running my integration tests.

Adding a field to the response DTO fixed the issue.

Waiter answered 30/7, 2019 at 9:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.