Introduction
In this example I am going to show you how to use Spring’s MultiValueMap in REST API. This MultiValueMap is similar to the Jersey’s MultivaluedMap. A MultiValueMap<K, V>
or MultivaluedMap<K, V>
is a map of key-values pairs. Each key can have zero or more values, where K
– the type of keys maintained by this map and V
– the type of mapped values.
This type of multi-value map is mainly used for storing header values in the request. Your REST API endpoint may take several parameters with multiple values. So, for the same key you can add multiple values in the multi-valued map.
For example, let’s say you want to pass different values for the same key in the HTTP header and the code for this would be similar to the following snippets:
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("Accept-Encoding", "compress;q=0.5");
map.add("Accept-Encoding", "gzip;q=1.0");
Related Post:
Prerequisites
Java 1.8+, maven 3.8.5, Spring Boot 2.7.0
Project Setup
The following pom.xml file can be used for the maven based project:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.roytuts</groupId>
<artifactId>springboot-rest-api-multivaluemap</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
REST Controller
I am creating a simple REST endpoint to receive the request in the MultiValueMap and sending those values after extraction as a response to the client.
package com.roytuts.springboot.rest.api.multivaluedmap.rest.controller;
import java.util.stream.Collectors;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AppRestController {
@PostMapping("/multiValueMap")
public ResponseEntity<String> multiValueMap(@RequestBody MultiValueMap<String, String> multiValueMap) {
String encoding = multiValueMap.get("Accept-Encoding").stream().map(String::toString)
.collect(Collectors.joining(","));
String contentType = multiValueMap.get("Content-Type").get(0);
return new ResponseEntity<String>(encoding + "," + contentType, HttpStatus.OK);
}
}
In the above code snippets, I am joining the values for the same key or if I am sure that I have only one value then I am extracting the 0th value from the List.
Spring Boot Main Class
Here the main class will deploy the app into the embedded Tomcat server.
package com.roytuts.springboot.rest.api.multivaluedmap;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
Testing using REST Client
Either you can write a client program using any programming language or you can use any REST client tool to test the REST API. I will show you both ways of testing the service API.
REST Client – Spring Boot Program
I am writing Spring Boot Java program to test the REST service.
REST Template Config
In order use the RestTemplate from Spring framework you need to configure RestTemplate bean. RestTemplate bean provides number of useful methods to invoke REST APIs seamlessly.
package com.roytuts.springboot.rest.api.multivaluemap.client.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestClientConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
Invoking REST API
Here is the code snippets that invoke the REST API using the MultiValueMap parameter.
package com.roytuts.springboot.rest.api.multivaluemap.client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class App implements CommandLineRunner {
@Autowired
private RestTemplate restTemplate;
public static void main(String[] args) {
SpringApplication.run(App.class, args).close();
}
@Override
public void run(String... args) throws Exception {
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("Accept-Encoding", "compress;q=0.5");
map.add("Accept-Encoding", "gzip;q=1.0");
map.add("Content-Type", MediaType.APPLICATION_JSON_VALUE);
String response = restTemplate.postForObject("http://localhost:8080/multiValueMap", map, String.class);
System.out.println("Response: " + response);
}
}
Notice how I have created MultiValueMap instance and how I have stored key/values pairs.
Make sure you have already started the REST service application. Now, when you execute the above main class, you will see the following response from the REST service:
Response: compress;q=0.5,gzip;q=1.0,application/json
REST Client – Postman
Next I am using REST client tool Postman to test the REST service. You will also learn how to form the request body in Postman tool for MultiValueMap parameter.
You cannot pass the input request as JSON value so, I am passing as key/value pairs as a x-www-form-urlencoded.