Announcement Announcement Module
No announcement yet.
REST POST with MultiValueMap is always empty Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • REST POST with MultiValueMap is always empty

    I've just started working with Spring 3.0 M3 to write a REST API for use instead of an existing SOAP API. I followed the instructions for creating a restful service. Any methods that I've annotated as POST that take a @RequestBody MultiValueMap never receive a populated Map. If I create an equivalent method with a PUT the map is successfully populated. Here's two examples:

    @RequestMapping(value = "/service/postTest", method = RequestMethod.POST)
    public String testPost(@RequestBody MultiValueMap<String, Object> params,
    Model model)
    return "redirect:/service/token/" + 1;

    @RequestMapping(value = "/service/putTest", method = RequestMethod.PUT)
    public void testPut(@RequestBody MultiValueMap<String, Object> params,
    Model model)

    As you can see the two methods are identical except for the URI, request method, and the PUT doesn't return a value. I'm using the RestTemplate in a simple main method to call the methods. I tried running the WAR file I created in glassfish, tomcat 6, and jetty 6. Both glassfish and tomcat exhibited the same behavior. Jetty however also exhibited the problem with the PUT method. I tried changing the MultiValueMap above to a String and this worked for POSTing in both Jetty and glassfish. I tried debugging the spring code to find the problem and I found that in the FormHttpMessageConverter method readInternal line 66 is where the problem shows up. In cases where no parameters are returned the input reader doesn't return any data in the copyToString method.

    Is there anything that I'm doing wrong? I can provide more information if needed.

  • #2
    I'm having this exact same problem, though I'm POSTing through a very basic form within an HTML file.

    public class TrackingController {
    	@RequestMapping(value = "/events", method=RequestMethod.POST)
    	public void logEvent(@RequestBody MultiValueMap<String,Object> params) {
    		for (String key : params.keySet()) {
    			System.out.println("key: " + key);
    			System.out.println("value: " + params.get(key));
    Here is the form:

            <title>Log Event</title>
            <h1>Log Event</h1>
    		<form  action="http://localhost:8080/tracking/events" method="post">
    		            <td>First Name:</td>
    		            <td><input type="text" name="firstName" /></td>
    		            <td>Last Name:</td>
    		            <td><input type="text" name="lastName" /></td>
    		            <td colspan="3">
    		                <input type="submit" value="Log Event" />


    • #3
      We never found a solution to this problem. We've been using @RequestBody with JAXB generated types or @RequestParam. This works for us but it seems like a large missing feature not to allow URL encoded parameters in the message body of a POST or PUT. I'm not sure how BigErn001 will be able to work around this problem since he's using an HTML form. You may have to switch to a GET and use @RequestParam.


      • #4
        I found a solution, at least for my problem. In debugging the FormHTTPMessageConverter, I notced the request body was always null. I guessed that the HiddenHTTPMethodFilter might be screwing around with the request contents so I removed it from web.xml and after that my MultiValueMap started getting populated.

        Here's what I removed:


        • #5
          Should be raised as bug

          I believe this should be raised as a bug:
          1. HiddenHttpMethodFilter reads via request.getParameter
          2. causing the ServletRequest.inputStream to be read
          3. FormHttpMessageConverter reads from servletRequest.getInputStream() which will be blank since it was already read.

          Did anybody raise this in JIRA currently?


          • #6
            JIRA Issue

            Looks like this issue has been added related to :


            • #7
              public boolean containsKey(java.lang.Object key)

              Returns true if this map contains at least one value for the specified key.

              Specified by:
              containsKey in interface java.util.Map<K,V>
              containsKey in class java.util.AbstractMap<K,V>

              key - key whose presence in this map is to be tested
              true if this map contains at least one value for the key, false otherwise.
              java.lang.ClassCastException - if the key is of an inappropriate type for this map.
              java.lang.NullPointerException - if the key is null and this map does not not permit null keys.