Adding parameters and Uploading file in Springboot REST Client

In my previous post, I wrote about Springboot REST Client and how easy it is to make HTTP requests with it. You can read it here. In this post, I will expand on that note and demonstrate how to add Request Parameters in HTTP requests and also how to send files as a Multipart Form-Data.

Example scenario

Let’s assume we are requesting for a list of available products from an e-commerce store API. The ResponseDTO.class looks like this.

class ResponseDTO<T>{
    int status;
    String message;
    T products;
}

and the Product.class looks like this.

class Product{
    UUID productId;
    String name;
    float pricePerUnit;
    int availableUnits;
}

Adding parameters

Now, let’s do the actual request. In order to request for all available products we need to send an api-key and the product-type as request parameters. These parameters are added to the body as a MultiValueMap<T,T> and we use the LinkedMultiValueMap<T,T> data structure to store these parameters.

public void sendPostWithParams(){
        RestClient client = getRestClient();

        MultiValueMap<String,String> params = new LinkedMultiValueMap();

        params.add("api-key",SECRET_KEY);
        params.add("product-type",productType);

        ResponseDTO<Product[]> products = client.uri("/api/v1/products")
            .body(params)
            .retrieve()
            .body(new ParameterizedTypeReference<ResponseDTO<Product[]>>() {});
}

Instead of sending the parameters directly on the body, we can also use the URIBuilder to build the url and append some parameters to the URL. Let’s say, we need to request for a specific product with a productId. We can append the productId on the API URL.

public void sendPostWithParamsWithUriBuilder(){
        RestClient client = getRestClient();

        MultiValueMap<String,String> params = new LinkedMultiValueMap();

        params.add("api-key",SECRET_KEY);
        params.add("product-type",productType);

        ResponseDTO<Product> products = client
            .uri(
                (uriBuilder) -> uriBuilder.path("/api/v1/products/{productId}")
                                    .queryParams(params)
                                    .build(productId)
            )
            .retrieve()
            .body(new ParameterizedTypeReference<ResponseDTO<Product>>() {});
}

Notice that, we need to match the variable name we pass in the build method with the path variable name we write in the URL.

Uploading file

In case of files, we need to add the file as a Resource. There are multiple implementations of the Resource interface which can be chosen depending on the requirements. For this example, we are going to use FileSystemResource.

public void sendPostWithFile(){
        RestClient client = getRestClient();

        File imageFile = new File(filePath);

        MultiValueMap<String,Object> params = new LinkedMultiValueMap();

        params.add("api-key",SECRET_KEY);
        params.add("product-id",productId);
        params.add("product-image",new FileSystemResource(imageFile));

        ResponseDTO response = client.uri("/api/v1/products")
            .body(params)
            .retrieve()
            .toEntity(ResponseDTO.class);
}

Notice that, we changed the Type Definition of MultiValueMap to <String,Object> as we are sending a file object as Multipart data.

When Spring detects a Resource in the parameters data structure, it automatically sets the request content-type header as multipart/form-data. Otherwise, it is set to x-www-form-urlencoded.

Leave a Reply