Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my Spring service returning any content type requested by client?

I have a Spring rest service using Spring 3.1.0.RELEASE. Here is the relevant code for the service call in question:

@RequestMapping(value="/{var1}", method=RequestMethod.GET, produces="application/json")
@ResponseBody
public String getSomeStuff(@PathVariable final String var1) {
    return myJsonString;
}

If I call this using the following curl command, it happily returns me my json string with a content-type of application/xml whereas I would expect a 406 based on the Spring 3.1 docs:

curl -v -H "Accept: application/xml" http://localhost:8080/MyServiceSite/myvalue

There is no extra configuration in my app for this service (no serialization), I am returning raw json with no post-processing for the service configured. I'm certain I have missed something, can anyone point out anything I may have missed?

Edit: Here is the documentation I was looking at when attempting to get this working. Specifically section 16.3.2.5. My code is very similar except that their code looks like it assumes config setup to let Spring handle serialization. Perhaps the produces does not work when bypassing the Spring serialization?

Edit: I changed my expectation for the response code. A 415 would indicate I was sending improper content in my request body whereas 406 is proper for having an accept header that doesn't jive with the content type of the server.

Anyway, I have changed this method do return a Map and added config for it to serialize to json and now if I send an invalid content type from the client I get the proper 406 response. It seems that maybe the "produces" setting is ignored when the output of the method is not being serialized.

like image 894
mockobject Avatar asked Nov 04 '22 06:11

mockobject


2 Answers

The produces condition is new to Spring MVC 3.1 and is only supported with the RequestMappingHandlerMapping and related @MVC support classes, also new in Spring 3.1. My guess is that you're using the 3.0 @MVC support classes, which do not support the produces condition. Your code otherwise is correct and so are your expectations of what should happen.

The use of headers="Accept=application/json" is unnecessary in 3.1. That's exactly what the produces condition was introduced for.

like image 112
Rossen Stoyanchev Avatar answered Nov 08 '22 00:11

Rossen Stoyanchev


What about the headers attribute for the @RequestMapping. You could set the Accept header in there. Something like:

@RequestMapping(value="/{var1}", method=RequestMethod.GET, produces="application/json", headers = "Accept=application/json")
@ResponseBody
public String getSomeStuff(@PathVariable final String var1) {
    return myJsonString;
}

I don't know how Spring would handle a request to that path without a matching header. If it doesn't give what you want you might need to define a similar mapping without the headers and have it send back a ResponseEntity and set the response code or something, but I would hope it would handle it appropriately.

like image 27
digitaljoel Avatar answered Nov 07 '22 22:11

digitaljoel