Search code examples
springresttemplatedtoquery-string

Populate query parameters from DTO


Is there a way to let Spring populate RestTemplate query parameters automatically from a DTO, similarly to how it instantiates the response DTO automatically?

I wish to write something like:

RequestDto request = new RequestDto();
request.setFoo("foo");
request.setBar("bar");

ResponseDto response = restTemplate.getForObject(
        "http://example.com/api",
        ResponseDto.class, 
        request
);

Instead of:

ResponseDto response = restTemplate.getForObject(
        "http://example.com/api?foo={foo}&bar={bar}",
        ResponseDto.class,
        "foo",
        "bar"
);

Because there are many large DTOs, requiring tons of boilerplate code, which must be kept in sync with any DTO changes.

Spring 4.3.25


Solution

  • I don't think that is directly possible. The following is not exactly using the DTO, but it does let you build the request without having to form the URL string manually. You can use Spring's UriComponentsBuilder class.

    UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://example.com/api")
        .queryParam("foo", "bar")
        // etc. ...
        .queryParam("bar", "foo");
    
    String result = restTemplate.getForObject(builder.toString(), String.class);
    

    You could loop over the DTO and build the query as above. Or without the DTO, you could use a Map<String, String> and loop over it.

    Map<String, String> params = new HashMap<>();
    params.put("foo", "bar");
    
    UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://example.com/api");
    for (Map.Entry<String, String> entry : params.entrySet()) {
        builder.queryParam(entry.getKey(), entry.getValue());
    }
    String result = restTemplate.getForObject(builder.toString(), String.class);
    

    Edit:

    As crizzis suggested below, you can use Spring Cloud OpenFeign's REST Client (from Feign @QueryMap support):

    The OpenFeign @QueryMap annotation provides support for POJOs to be used as GET parameter maps. Unfortunately, the default OpenFeign QueryMap annotation is incompatible with Spring because it lacks a value property.

    and

    Spring Cloud OpenFeign provides an equivalent @SpringQueryMap annotation, which is used to annotate a POJO or Map parameter as a query parameter map.

    From your question's example:

    public class RequestDto {
      private string foo;
      private string bar;
    }
    
    @FeignClient(name = "client", url = "http://example.com")
    public interface FooTemplate {
    
        @GetMapping(path = "/api")
        String endpoint(@SpringQueryMap RequestDto requestDto);
    }