添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I have a @GetMapping @RestController that could produce both xml and json.
If Content-Type is missing in the clients' request, by default json should be returned.

I therefor tried to set ContentNegotiationConfigurer , but without any effect:

.w.s.m.s.DefaultHandlerExceptionResolver :
Resolved [org.springframework.http.converter.HttpMessageNotWritableException:
No converter for [class java.util.ImmutableCollections$Set12] with preset Content-Type 'null']

@Configuration
public class WebConfig implements WebMvcConfigurer {
	@Override
	public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
		configurer.defaultContentType(MediaType.APPLICATION_JSON);
@RestController
public class ExampleServlet {
	@GetMapping(value = "/test", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
	public Set<String> test() {
		return Set.of("test");

When I change the code to produces=APPLICATION_JSON_VALUE only, everything works as expected. So the servlet in general should be fine.

spring-boot-2.7.4

Okay, I think Content-Type from clients perspective is wrong in this issue, I probably ment Accept-Encoding.

While I cannot reproduce exactly, let me ask: does setting configurer.defaultContentType() forcibly exclude or prohibit any other content type? Or is it just a "favor", and other content types are still allowed?

Because when I set configurer.defaultContentType(APPLICATION_JSON) or configurer.defaultContentType(APPLICATION_JSON, APPLICATION_XML), I'm unable to let spring produce xml output:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.defaultContentType(MediaType.APPLICATION_JSON);
        //configurer.defaultContentType(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML);
@RestController
public class ExampleServlet {
    @GetMapping(
            value = "/both",
            produces = {
                    MediaType.APPLICATION_XML_VALUE,
                    MediaType.APPLICATION_JSON_VALUE
    public Set<String> both() {
        return Set.of("both");
    @GetMapping(
            value = "/xml",
            produces = {
                    MediaType.APPLICATION_XML_VALUE
    public Set<String> xml() {
        return Set.of("xml");
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>untitled</artifactId>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.8</version>
    </parent>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>
    </dependencies>
</project>

Both can't produce xml:

curl --location --request GET 'localhost:8080/test' --header 'Accept-Encoding: application/xml':

[both]

curl --location --request GET 'localhost:8080/both' --header 'Accept-Encoding: application/xml':

2023-01-31 11:45:47.436  WARN 38445 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver :
Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation]

So the issue is still relevant: XML media type in content negotiation is not taken into account!

Also the following properties don't help:

spring.mvc.contentnegotiation.media-types.json=application/json
spring.mvc.contentnegotiation.media-types.xml=application/xml

The following still gives json output:
curl --location --request GET 'localhost:8080/both?format=xml' --header 'Accept-Encoding: application/xml'

untitled.zip

Okay, I think Content-Type from clients perspective is wrong in this issue, I probably ment Accept-Encoding.

I think you meant the Accept request header instead, as using this header with your sample application behaves as expected.

I'm closing this issue now.

I don't understand. Running your sample application, here's the behavior.

With configurer.defaultContentType(MediaType.APPLICATION_JSON);

$ http :8080/both Accept:"*/*"
HTTP/1.1 200
Connection: keep-alive
Content-Type: application/json
Date: Tue, 31 Jan 2023 18:36:36 GMT
Keep-Alive: timeout=60
Transfer-Encoding: chunked
    "both"
$ http :8080/both Accept:"application/xml"
HTTP/1.1 200
Connection: keep-alive
Content-Type: application/xml
Date: Tue, 31 Jan 2023 18:37:01 GMT
Keep-Alive: timeout=60
Transfer-Encoding: chunked
  <item>both</item>
$ http :8080/both Accept:"application/json"
HTTP/1.1 200
Connection: keep-alive
Content-Type: application/json
Date: Tue, 31 Jan 2023 18:37:05 GMT
Keep-Alive: timeout=60
Transfer-Encoding: chunked
    "both"

Same behavior applies for configurer.defaultContentType(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML);, as ordering is taken into account (see javadoc).

For example, changing the order with configurer.defaultContentType(MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON); result in a single behavior change:

$ http :8080/both Accept:"*/*"
HTTP/1.1 200
Connection: keep-alive
Content-Type: application/xml
Date: Tue, 31 Jan 2023 18:39:41 GMT
Keep-Alive: timeout=60
Transfer-Encoding: chunked
  <item>both</item>

Using the following configuration properties (which are mentioned in this issue but missing from the sample:

spring.mvc.contentnegotiation.favor-parameter=true
spring.mvc.contentnegotiation.media-types.json=application/json
spring.mvc.contentnegotiation.media-types.xml=application/xml

We can see the parameter used for content negotiation:

$ http -v :8080/both format==json
GET /both?format=json HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8080
User-Agent: HTTPie/3.2.1
HTTP/1.1 200
Connection: keep-alive
Content-Type: application/json
Date: Tue, 31 Jan 2023 18:44:59 GMT
Keep-Alive: timeout=60
Transfer-Encoding: chunked
    "both"
$ http -v :8080/both format==xml
GET /both?format=xml HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8080
User-Agent: HTTPie/3.2.1
HTTP/1.1 200
Connection: keep-alive
Content-Type: application/xml
Date: Tue, 31 Jan 2023 18:45:23 GMT
Keep-Alive: timeout=60
Transfer-Encoding: chunked
  <item>both</item>

This is all working as expected from my point of view.
Could you explain precisely what the problem is with this behavior?

Your explanation is exactly what I would have expected, but was not when adding the sample app.
Maybe this is a local machine issue. Will try tomorrow and report back!