javaspring-mvchttp-accept-header

Why RequestMappings with the same URL but producing different MediaTypes works?


I want to understand why Spring application is starting if I have same 2 requestMapping URL,params(no params) and produces type(JSON).By default the methods is producing JSON(I tested XML and others and I get 500 error, I don't have dependencies).I want to know if it is a Intellij or Spring problem,or is it normal to start and to get overriden second Get becouse if I put produces = MediaType.APPLICATION_JSON_VALUE on the second too,I get error.Here is the example that work:

@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<ExampleDTO>> getMethodd1() {
    return ResponseEntity.ok(ExampleStore.available);
}
@GetMapping()
public ResponseEntity<List<ExampleDTO>> getMethodd2() {
    return ResponseEntity.ok(ExampleStore.available);
}

And this example doesn't start anymore:

@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<ExampleDTO>> getMethodd1() {
    return ResponseEntity.ok(ExampleStore.available);
}
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<ExampleDTO>> getMethodd2() {        
    return ResponseEntity.ok(ExampleStore.available);
}

PS:I know a request should be different by params or url.


Solution

  • I think it is quite obvious if you think it a little further. See these three controller methods with the same url:

    @GetMapping(path = "/sameurl")
    public String text() throws JsonProcessingException {
        return "some data\n";
    }
    
    @GetMapping(path = "/sameurl", produces = MediaType.APPLICATION_XML_VALUE)
    public String xml() throws JsonProcessingException {
        return "<data>some data</data>\n";
    }
    
    @GetMapping(path = "/sameurl", produces = MediaType.APPLICATION_JSON_VALUE)
    public String json() throws JsonProcessingException {
        return "{\"data\": \"some data\"}\n"; 
    }
    

    As you saw already in your question that what distinguishes them is what each method produces.

    The method that is actually invoked is selected by what client accepts which gives you the flexiblity to choose at the controller level how to process the request without checking accept types yourself.

    With above API urls and corresponding calls the results:

    curl -H "Accept:application/someformat" localhost:8080/sameurl
    

    some data

    curl -H "Accept:application/json" localhost:8080/sameurl
    

    {"data": "some data"}

    curl -H "Accept:application/xml" localhost:8080/sameurl
    

    <data>some data</data>

    What then is an actual duplicate is a request mapping having the same URL and same type to produce. There is no distinguishing attribute anymore and Spring can not tell which method to use.