I have two Spring MVC controller methods. Both receive the same data in the request body (in the format of an HTLM POST
form: version=3&name=product1&id=2
), but one method handles PUT
requests and another DELETE
:
@RequestMapping(value = "ajax/products/{id}", method = RequestMethod.PUT) @ResponseBody public MyResponse updateProduct(Product product, @PathVariable("id") int productId) { //... } @RequestMapping(value = "ajax/products/{id}", method = RequestMethod.DELETE) @ResponseBody public MyResponse updateProduct(Product product, @PathVariable("id") int productId) { //... }
In the first method, all fields of the product
argument are correctly initialised. In the second, only the id
field is initialised. Other fields are null
or 0. (id
is, probably, initialised because of the id
path variable).
I can see that the HttpServletRequest
object contains values for all fields in the request body (version=3&name=product1&id=2
). They just are not mapped to the fields of the product
parameter.
How can I make the second method work?
I also tried to use the @RequestParam
annotated parameters. In the method that handles PUT
requests, it works. In the DELETE
method, I get an exception: org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'version' is not present
.
I need to pass data in the body of DELETE
requests because the data contain a row version which is used for optimistic locking.
delete() is the Axios options, not the request body. You can't pass the request body as the 2nd parameter like you can with axios.
Requests using GET should only be used to request data (they shouldn't include data). Note: Sending body/payload in a GET request may cause some existing implementations to reject the request — while not prohibited by the specification, the semantics are undefined.
The short answer is: You should include a response body with an entity describing the deleted item/resource if you return 200. 202 is something like an asynchronous request/response return status.
The problem is not a Spring
problem, but a Tomcat
problem.
By default, Tomcat will only parse arguments that are in the form style, when the HTTP method is POST
(at least for version 7.0.54 that I checked but it's probably the same for all Tomcat 7 versions).
In order to be able to handle DELETE methods as well you need to set the parseBodyMethods
attribute of the Tomcat Connector. The connector configuration is done in server.xml
.
Your updated connector would most likely look like:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" parseBodyMethods="POST,PUT,DELETE" URIEncoding="UTF-8" />
Here is documentation page for configuring Tomcat connectors.
Once you setup Tomcat to parse the parameters, Spring will work just fine (although in your case you will probably need to remove @RequestBody
from the controller method)
You can try adding the annotation @RequestBody to your Product argument.
But if you just need to pass version information, using a request param is more appropriate.
So add a new argument in your delete method @RequestParam("version") int version, and when calling the delete method pass a query param like ..ajax/products/123?version=1
As you said request param is not working for you in delete, can you post the exact url you used and the method signature ?
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