Spring RestTemplate - Passing in object parameters in GET

17,566

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.

Share:
17,566
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    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
    g00glen00b almost 8 years
    No, the second parameter (String.class) is used to describe the return type of the response. The response in both /get1 and /get2 is a String it's the request parameter that changes.
  • Admin
    Admin almost 8 years
    Works perfectly. Thanks!
  • hublo
    hublo over 6 years
    Great 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
    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.