I have a simple method (running on Tomcat 6.0.35) that looks like so:
@RequestMapping(value = "/bla/d", method = RequestMethod.DELETE)
@ResponseStatus(HttpStatus.NO_CONTENT)
public void d(@RequestParam String d){
//logic here
}
When I send a DELETE request with post like parameters (d=gggg in the body) I get a 400 Bad Request. But if I change it to
@RequestMapping(value = "/bla/d", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.NO_CONTENT)
public void d(@RequestParam String d){
//logic here
}
It works perfectly. I was using a Firefox Add-on to test it (and python and Spring's RestTemplate with same result) here's how the request look with POST(a is a cope pasted method named a with parameter a):
POST /bla/a HTTP/1.1
Host: ~~~~:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 7
Pragma: no-cache
Cache-Control: no-cache
a=asdas
HTTP/1.1 204 No Content
Server: Apache-Coyote/1.1
Date: Tue, 12 Jun 2012 09:29:46 GMT
And delete looks like:
DELETE /bla/d HTTP/1.1
Host: ~~~~~:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 7
d=asdas
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 971
Date: Tue, 12 Jun 2012 09:30:04 GMT
Connection: close
Please help me, I might be missing something stupid but I just can't see it. My original problem was sending an array via post-like body with DELETE request but it seems that something more basic is wrong.
In Spring MVC, the @RequestParam annotation is used to read the form data and bind it automatically to the parameter present in the provided method. So, it ignores the requirement of HttpServletRequest object to read the provided data.
@RequestParam is a Spring annotation used to bind a web request parameter to a method parameter. It has the following optional elements: defaultValue - used as a fallback when the request parameter is not provided or has an empty value. name - name of the request parameter to bind to.
The @PathVariable annotation is used for data passed in the URI (e.g. RESTful web services) while @RequestParam is used to extract the data found in query parameters.
When you have a method annotated with @ModelAttribute , it is being called every time code hits that servlet. When you have @ModelAttribute as one of the method's parameters, we are talking about incoming Http form data-binding. Calling @RequestParam is a shortcut for saying request.
Well after doing some research and debugging I've found out that Spring's ServletWebREquest calls getParameterValues of org.apache.catalina.connector.RequestFacade.getParameterValues which calls getParameterValues in which I've found the following line (Request.java 2599-2600):
if (!getMethod().equalsIgnoreCase("POST"))
return;
Which kills any attempt to send POST-like parameters with DELETE which means Tomcat is actively restricts this use-case even though the RFC does not restrict such usage(although it does say that some existing implementations may reject such requests, Tomcat just throws it's parameters away). What brings one that's using Spring and Tomcat and trying to send a DELETE requests with parameters to ugly solutions like getting all the request body with @RequestBody and extracting it manually which makes your supposedly innocent method that just wants to delete something aware of some a Map that contains the request body.
@fmucar
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With