Search code examples
javaspringspring-bootgetresttemplate

Spring RestTemplate - Passing in object parameters in GET


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.


Solution

  • 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.