Using PUT and DELETE methods in Spring MVC
Asked Answered
K

2

21

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.

Kassia answered 29/11, 2012 at 15:57 Comment(0)
L
18

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.

Lehet answered 30/11, 2012 at 19:37 Comment(4)
I'm using that tag library - <form:form>...</form:form> and the hidden field <input type="hidden" name="_method" value="PUT"/> is automatically included in the generated HTML as shown in the second and third code snippets in the question. I have already seen so many posts on this site as well as other tutorials. I'm almost doing as described by them though the thing doesn't work, in my case. I'm not sure what I'm missing. Thanks for the answer.Kassia
Your text, "The NoSuchBeanDefinitionException is most probably an unrelated problem" is correct. The only problem was that I had misconfigured this org.springframework.web.multipart.commons.CommonsMultipartResolver and placed in a wrong xml file instead of placing it in applicationContext.xml. Hence, it was causing the exception. It now works and the method designated with RequestMethod.PUT in the Spring controller is invoked. One problem still remains is that ServletFileUpload.isMultipartContent(request) always returns false. It returns true only on POST. Do you know the reason?Kassia
Difficult to guess ... first thing that comes to mind: are you sure that your PUT request is a multipart request (I know, dumb question, but sometimes the aswer is obvious).Lehet
No problem, I will post this as a new question. By the way, yes it is a multipart request with enctype="multipart/form-data" and method="put". Thank you.Kassia
P
1

You should change your config.

<servlet-name>/*</servlet-name>  

to

<servlet-name>[dispatch servlet name]</servlet-name> 
Participation answered 31/10, 2014 at 11:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.