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.
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.