Spring RestTemplate - Passing in object parameters in GET
When you're using a complex object (like MyObj
) as a @RequestParam
, Spring will try to convert a string to that complex object. In this case, because MyObj
has only a single String
field called inputValue
it will automagically use whatever value you provide to your query parmeter to fill the property in your object.
For example, if you call: http://localhost:8080/get2?parm=foobar
you'll get a MyObj
where inputValue
will be "foobar"
.
If you use RestTemplate
you shouldn't get an error, but in stead it will try to convert new MyObj("Test input 2")
to a string, using the toString()
method and the response will be:
You entered com.example.MyObj@63a815e8
This is probably not what you want. Generally you don't want to pass complex objects as request parameters, you can use @RequestBody
with RequestMethod.POST
and restTemplate.postForEntity()
to properly pass your MyObj
as JSON.
Change your controller like this:
@RequestMapping(value = "/get2", method = RequestMethod.POST)
public ResponseEntity<String> get2(@RequestBody MyObj parm) {
String response = "You entered " + parm.getInputValue();
return new ResponseEntity<>(response, HttpStatus.OK);
}
And call it using RestTemplate
like this:
MyObj myObj = new MyObj("Test input 2");
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.postForEntity("http://localhost:8080/get2", myObj, String.class).getBody();
This will properly pass your object as JSON.
Admin
Updated on June 04, 2022Comments
-
Admin almost 2 years
How do I use the RestTemplate to pass in an object as a parameter? For instance, say that I had the following services set up with Spring Boot:
@RequestMapping(value = "/get1", method = RequestMethod.GET) public ResponseEntity<String> get1(@RequestParam(value = "parm") String parm) { String response = "You entered " + parm; return new ResponseEntity<String>(response, HttpStatus.OK); } @RequestMapping(value = "/get2", method = RequestMethod.GET) public ResponseEntity<String> get2(@RequestParam(value = "parm") MyObj parm) { String response = "You entered " + parm.getValue(); return new ResponseEntity<String>(response, HttpStatus.OK); }
If a client wanted to call the first service, they could use the following:
//This works fine RestTemplate restTemplate = new RestTemplate(); String response = restTemplate.getForObject("http://localhost:8080/get1?parm={parm}", String.class, "Test input 1");
But if a client wanted to call the second service, they get a 500 error using the following:
//This doesn't work MyObj myObj = new MyObj("Test input 2"); RestTemplate restTemplate = new RestTemplate(); String response = restTemplate.getForObject("http://localhost:8080/get2?parm={parm}", String.class, myObj);
The MyObj class looks like this:
@JsonSerialize public class MyObj { private String inputValue; public MyObj() { } public MyObj(String inputValue) { this.inputValue = inputValue; } public String getInputValue() { return inputValue; } public void setInputValue(String inputValue) { this.inputValue = inputValue; } }
I'm assuming that the problem is that the myObj is not getting properly setup as a parameter. How do I go about doing this?
Thanks in advance.
-
g00glen00b almost 8 yearsNo, the second parameter (
String.class
) is used to describe the return type of the response. The response in both/get1
and/get2
is aString
it's the request parameter that changes. -
Admin almost 8 yearsWorks perfectly. Thanks!
-
hublo over 6 yearsGreat answer! Actually, lots of popele (if not everyone :) ) always marshal/unmarschal objects as JSON. I'm always wondering why not implementing an interface in both client and server side? As long as you don't open your service to the world, I believe it perfectly make it ...
-
g00glen00b over 6 years@hublo That's what I often do at projects, the REST client on the consumer side could implement the same interface as the REST service on the other side.