Reputation:
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.
Upvotes: 2
Views: 20713
Reputation: 183
i'm guessing this:
String response = restTemplate.getForObject("http://localhost:8080/get2?parm={parm}", String.class, myObj)
should change as
String response = restTemplate.getForObject("http://localhost:8080/get2?parm={parm}", MyObj.class, myObj)
Upvotes: -2
Reputation: 44665
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.
Upvotes: 4
Reputation: 12024
You have to pass value of each URI parameter after responseType
. Problem is that RestTemplate
does not know how to map your object to URI parameters. You have to explicitly call appropriate myObj
method to retrieve the actual value:
String response = restTemplate.getForObject(
"http://localhost:8080/get2?parm={parm}", String.class,
myObj.getInputValue());
Signature of the getForObject
method you call is:
public <T> T getForObject(String url, Class<T> responseType, Object... urlVariables) throws ….
where urlVariables
is array of URI variable values to expand the URI with.
Upvotes: 0