HttpMediaTypeNotAcceptableException after upgrading to Spring 3.2

java, spring, spring-3, spring-mvc

Solution

There have been several changes related to how Spring does content-negotiations in 3.2. One of these changes is that content negotiations can now be done based on the file suffix in the URL. This feature is enabled by default. In Spring versions prior to 3.2 the HTTP accept-header were used for content-negotiations. When browsers accessed your URLs content-negotiation was seldom an issue, as browser always sends `Accept:(...)*/*`.

Spring has a map of suffix => Media type. For ".js" the default media type is "application/x-javascript". When Spring tries to lookup the handler mapping for a request to /resources/foo.js, it won't match your `foo()`-method as it produces the wrong media type.

I'm not sure if the Spring team has thought through this case. It is at least a bit strange that it lets you create a `@RequestMapping` which cannot be accessed (because of the incompatibility between the .js-media type and what is set in the produces field).

There are several ways of fixing this issue. One is to change the produces-parameter to "application/x-javascript". Another would be to change the media type of ".js" to "text/javascript" (see the docs of how to do that). A third possibility is to turn off content-negotiations based on suffixes (again, see the docs of how to do it).

Problem

After upgrading my Spring MVC application to Spring 3.2 I'm getting the following exception when accessing some of my URLs: ``` org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:203) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:272) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:212) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:55) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:297) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1091) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1076) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:896) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915) [spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE] (...) ``` This exception results to a HTTP 406 NOT ACCEPTABLE. I've managed to create a simplified controller with a URL I cannot access: ``` @RequestMapping(value = "/resources/foo.js", produces = "text/javascript") @ResponseBody public String foo() throws Exception { return ""; } ``` As I'm using a normal browser which has `*/*` in the `Accept`-header, I don't see why I should get a HTTP 406. What makes this even more strange is that this code is working with Spring 3.1.2, but not with Spring 3.2. Why is that?

Original source