Spring Framework
  1. Spring Framework
  2. SPR-7030

RequestMapping PUT method does not have any populate any parameters

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Won't Fix
    • Affects Version/s: 3.0.1
    • Fix Version/s: None
    • Component/s: Web
    • Labels:
      None

      Description

      I'm designing a RESTful webservice after successfully adding POST (create) requests I moved over to work on PUT (edit) requests. Upon testing the PUT methods I noticed there was a stack trace and a generic "put method not supported" warning along with the stack trace although when debugging the request mapped method is clearly invoked via debugger. I inspected further and noticed my "command" object and request parameters were not being bound whereas switching the method on the client and server to POST did have the appropriate bound parameters.

        Activity

        Hide
        Arjen Poutsma added a comment - - edited

        Hi Andy,

        Could you please give me the stacktrace you mentioned? The @Controller class would be useful to have as well.

        Show
        Arjen Poutsma added a comment - - edited Hi Andy, Could you please give me the stacktrace you mentioned? The @Controller class would be useful to have as well.
        Hide
        Andy Tran added a comment -

        Added an test case attachment.

        Show
        Andy Tran added a comment - Added an test case attachment.
        Hide
        Andy Tran added a comment -

        Also, as a note, I only got the stacktrace and the WARN for PUT not being supported because there was an NPE invoking the method with null parameters. Therefore the attached test case won't have a stack trace, the parameter is simply not bound.

        Show
        Andy Tran added a comment - Also, as a note, I only got the stacktrace and the WARN for PUT not being supported because there was an NPE invoking the method with null parameters. Therefore the attached test case won't have a stack trace, the parameter is simply not bound.
        Hide
        Arjen Poutsma added a comment -

        The reason for this is that Servlet containers only expose form-encoded data for POST requests (see section 4.1.1 of the servlet spec). Effectively, this means you can also use binding with POST or GET requests (with query parameters).

        The only workaround I can think of is to use the HiddenHttpMethodFilter, which can 'fake' a PUT by doing a POST with a hidden method field. Or you can use @RequestBody with the FormHttpMessageConverter, which reads from the request stream directly into a MultiValueMap. For instance:

        @RequestMapping(method = RequestMethod.PUT)
        public void put(@RequestBody MultiValueMap form, HttpServletRequest request, Writer writer) throws IOException {
            Command command = new Command();
            WebDataBinder dataBinder = new WebDataBinder(command);
            dataBinder.bind(new MutablePropertyValues(form.toSingleValueMap()));
        }
        
        Show
        Arjen Poutsma added a comment - The reason for this is that Servlet containers only expose form-encoded data for POST requests (see section 4.1.1 of the servlet spec). Effectively, this means you can also use binding with POST or GET requests (with query parameters). The only workaround I can think of is to use the HiddenHttpMethodFilter, which can 'fake' a PUT by doing a POST with a hidden method field. Or you can use @RequestBody with the FormHttpMessageConverter, which reads from the request stream directly into a MultiValueMap. For instance: @RequestMapping(method = RequestMethod.PUT) public void put(@RequestBody MultiValueMap form, HttpServletRequest request, Writer writer) throws IOException { Command command = new Command(); WebDataBinder dataBinder = new WebDataBinder(command); dataBinder.bind( new MutablePropertyValues(form.toSingleValueMap())); }
        Hide
        Arjan van B. added a comment - - edited

        Since Spring 3.1, HttpPutFormContentFilter can be used for PUT and PATCH requests:

        Filter that makes form encoded data available through the ServletRequest.getParameter*() family of methods during HTTP PUT requests.

        The Servlet spec requires form data to be available for HTTP POST but not for HTTP PUT requests. This filter intercepts HTTP PUT requests where content type is 'application/x-www-form-urlencoded', reads form encoded content from the body of the request, and wraps the ServletRequest in order to make the form data available as request parameters just like it is for HTTP POST requests.

        See SPR-5628, and the documentation in Working with "application/x-www-form-urlencoded" data.

        Show
        Arjan van B. added a comment - - edited Since Spring 3.1, HttpPutFormContentFilter can be used for PUT and PATCH requests: Filter that makes form encoded data available through the ServletRequest.getParameter*() family of methods during HTTP PUT requests. The Servlet spec requires form data to be available for HTTP POST but not for HTTP PUT requests. This filter intercepts HTTP PUT requests where content type is ' application/x-www-form-urlencoded ', reads form encoded content from the body of the request, and wraps the ServletRequest in order to make the form data available as request parameters just like it is for HTTP POST requests. See SPR-5628 , and the documentation in Working with "application/x-www-form-urlencoded" data .

          People

          • Assignee:
            Arjen Poutsma
            Reporter:
            Andy Tran
            Last updater:
            Arjan van B.
          • Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:
              Days since last comment:
              1 year, 12 weeks, 3 days ago