I have a RESTful spring based endpoint to get assets stored in a db to a javascript editor. The relevant parts boil down to:
@RestController
@RequestMapping(
It's not a bug, it's a feature...
As @axtavt and @rhinds have supposed, something is messing around which the content type. The browsers sends a correct Accept: application/json
but spring ignores this and uses the extension of the url (aarrgh). From the docs:
16.16.4 Configuring Content Negotiation
You can configure how Spring MVC determines the requested media types from the client for request mapping as well as for content negotiation purposes. The available options are to check the file extension in the request URI, the "Accept" header, a request parameter, as well as to fall back on a default content type. By default, file extension in the request URI is checked first and the "Accept" header is checked next.
The solution is quite simple as you can disable this "feature":
@Configuration
@EnableWebMvc
public class RestCommonsMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
}
See also Spring does not ignore file extension for xml-config.
I had required an extra step in my special case. I would like to add an extra information to @dirk-lachowski's great comment in case someone else needs. In my case I am importing an extension from WebMvcConfigurationSupport
class
@Configuration
@EnableWebMvc
@Import({ SearchWebMvcConfigurationSupport.class })
public class SearchSpringConfiguration extends WebMvcConfigurerAdapter {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
}
If you need to override requestMappingHandlerMapping
method then you also have to add m.setUseSuffixPatternMatch(false);
@Configuration
public class SearchWebMvcConfigurationSupport extends WebMvcConfigurationSupport {
@Override
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping m = super.requestMappingHandlerMapping();
m.setAlwaysUseFullPath(true); // This makes your endpoints receive full path, including servlet mapping (you probably will not need this)
m.setUseSuffixPatternMatch(false);
return m;
}
}