Using PUT and DELETE methods in Spring MVC

http-delete, http-post, http-put, spring, spring-mvc

Solution

Most browsers do not support `action=PUT` in HTML forms. They will just send `POST` requests instead. The HiddenHttpMethodFilter will help you get around the problem, but you have to include a hidden field `_method=PUT` in your form. If you use the spring:form taglib this will be done automatically for you, but your example seems to use plain HTML.

The `NoSuchBeanDefinitionException` is most probably an unrelated problem.

Problem

I'm trying to use `RequestMethod.PUT` and `RequestMethod.DELETE` in Spring MVC controller (version 3.0.2). There are three methods mapped with a URL in the Spring controller class as follows (PUT, GET and POST respectively, for the demonstration purpose only). ``` @RequestMapping(method = {RequestMethod.PUT}, value = {"admin_side/Temp"}, headers = {"content-type=multipart/form-data"}) public String update(@ModelAttribute("tempBean") TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response) { if (ServletFileUpload.isMultipartContent(request)) { System.out.println("true"); } System.out.println("Request method PUT"); return "admin_side/Temp"; } @RequestMapping(method = {RequestMethod.GET}, value = {"admin_side/Temp"}) public String showForm(@ModelAttribute("tempBean") TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response) { System.out.println("Request method GET"); return "admin_side/Temp"; } @RequestMapping(method = {RequestMethod.POST}, value = {"admin_side/Temp"}) public String onSubmit(@ModelAttribute("tempBean") TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response) { System.out.println("Request method POST"); return "admin_side/Temp"; } ``` When the page is loaded, the the `GET` method is invoked as obvious but in all other cases (when the page is submitted), the only method to be invoked is `POST`, the method designated with `RequestMethod.PUT` is never invoked. The Spring form contains only a submit button and an image browser as, ``` <form:form id="mainForm" name="mainForm" method="PUT" action="Temp.htm" enctype="multipart/form-data" commandName="tempBean"> <input type="file" id="myFile" name="myFile"/> <input type="submit" id="btnSubmit" name="btnSubmit" value="Submit"/> </form:form> ``` The generated HTML is as follows, ``` <form id="mainForm" name="mainForm" action="Temp.htm" method="post" enctype="multipart/form-data"> <input type="hidden" name="_method" value="PUT"/> <!--This hidden field is implicitly included--> <input type="file" id="myFile" name="myFile"/> <input type="submit" id="btnSubmit" name="btnSubmit" value="Submit"/> </form> ``` In my `spring-config.xml` (`dispatcher-servlet.xml` in my case), I have added a reference to `CommonsMultipartResolver`: ``` <bean id="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/> ``` and in my `web.xml` file, `HiddenHttpMethodFilter` is configured as follows, ``` <filter> <filter-name>MultipartFilter</filter-name> <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class> <init-param> <param-name>multipartResolverBeanName</param-name> <param-value>filterMultipartResolver</param-value> </init-param> </filter> <filter-mapping> <filter-name>MultipartFilter</filter-name> <servlet-name>/*</servlet-name> </filter-mapping> <filter> <filter-name>HiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>HiddenHttpMethodFilter</filter-name> <servlet-name>/*</servlet-name> </filter-mapping> ``` The `PUT` (and `DELETE` too) method is never invoked (with no exception or error). What am I missing here? Update : With the following configuration in `web.xml`, ``` <filter> <filter-name>MultipartFilter</filter-name> <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class> <init-param> <!-- Makes no difference, if excluded. --> <param-name>multipartResolverBeanName</param-name> <param-value>filterMultipartResolver</param-value> </init-param> </filter> <filter-mapping> <filter-name>MultipartFilter</filter-name> <servlet-name>dispatcher</servlet-name> <!--Changed from /* to dispatcher--> </filter-mapping> <filter> <filter-name>HiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>HiddenHttpMethodFilter</filter-name> <servlet-name>dispatcher</servlet-name> <!--Changed from /* to dispatcher--> </filter-mapping> ``` it throws the following exception. org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'filterMultipartResolver' is defined Where the name `dispatcher` is the name of the Servlet - `org.springframework.web.servlet.DispatcherServlet` already mapped in web.xml as follows. ``` <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> ``` I'm not sure what else is needed? Is the filter `HiddenHttpMethodFilter` required to implement on our own extending `OncePerRequestFilter` something like the one shown here? (it is a built-in class) Important points are listed here.

Original source