3

I have a method in Spring rest service.

@RequestMapping(value = "test/process", method = RequestMethod.POST)
public @ResponseBody MyResponse processRequest(String RequestId, int count)

I am using Spring RestTemplate to call this service like this.

RestTemplate restTemplate = this.getRestTemplate();
MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
map.add("RequestId", RequestId);
map.add("count", count); 
restTemplate.postForObject(url, map,MyResponse.class);

When I try to invoke the client method I get the exception that no suitable HttpMessageConverter found for request type [java.lang.Integer]

org.springframework.http.converter.HttpMessageNotWritableException: Could not write request: no suitable HttpMessageConverter found for request type [java.lang.Integer]
at org.springframework.http.converter.FormHttpMessageConverter.writePart(FormHttpMessageConverter.java:310)
at org.springframework.http.converter.FormHttpMessageConverter.writeParts(FormHttpMessageConverter.java:270)
at org.springframework.http.converter.FormHttpMessageConverter.writeMultipart(FormHttpMessageConverter.java:260)
at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:200)
at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:1)
at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:596)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:444)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:409)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:287)

I know one of the ways is to pass all the parameters as String. But I might need to pass complex data types as parameters later. What is the ways to achieve this. I have googled and some option seem to be writing my own converters. How should I start about solving this problem.

d123
  • 437
  • 2
  • 6
  • 15
  • In the following line: map.add("RequestId", RequestId); is RequestId an object more complex than a string? Can we see the URL? Thanks! – java1337 Dec 09 '13 at 20:54
  • @java1337 RequestId is currently just a string but I might need to post a custom data types or a date object in other methods – d123 Dec 10 '13 at 08:10

1 Answers1

7

The root cause of this error is that by specifying an Integer in the LinkedMultiValueMap, the RestTemplate will take that to mean that your request is a multipart request. There is no HttpMessageConverter registered by default that can handle writing values of type Integer to a request body.

As you said, you can handle this situation by changing the count to be a String. After all, there is no Integer type in HTTP request parameters. However, you were worried

But I might need to pass complex data types as parameters later.

Assume something like this

public @ResponseBody MyResponse processRequest(String RequestId, int count, Complex complex) {

with

public class Complex {
    private String someValue;
    private int intValue;

    public String getSomeValue() {
        return someValue;
    }

    public void setSomeValue(String someValue) {
        this.someValue = someValue;
    }

    public int getIntValue() {
        return intValue;
    }

    public void setIntValue(int intValue) {
        this.intValue = intValue;
    }

    public String toString() {
        return someValue + " " + intValue;
    }
}

The the following will work just fine

MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
map.add("RequestId", "asd");
map.add("count", "42");
map.add("someValue", "complex");
map.add("intValue", "69");
restTemplate.postForObject(url, map,MyResponse.class);

Remember that the request parameters are used to populate the fields of model attributes by their names.

An even better solution would have you using a serialization standard like JSON or XML.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • Thanks for the reply. By "using a serialization standard like JSON or XML.", you mean that I should create a request object having RequestId,count and someValue as memebers. and post that object. controller should have the params as RequestBody MyClass myobject? – d123 Dec 11 '13 at 12:39
  • @aks No, I mean instead of sending request parameters, you should send JSON and XML. Spring supports those types with `@RequestBody` annotation on handler method parameters. – Sotirios Delimanolis Dec 11 '13 at 13:31