I have a multimap. When I try to send the data over to the backend-server from my frontend-server using restTemplate, it returns a "500 Internal Server Error" error code. It works for normal Map from the java.util.Map class. How do I configure restTemplate so that I send Google guava multimap data over?
This is my frontend-server code in spring boot.
import com.google.common.collect.Multimap;
...
try
{
RestTemplate rt = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
List<MediaType> acceptList = new ArrayList<>();
acceptList.add(MediaType.APPLICATION_JSON);
headers.setAccept(acceptList);
Multimap<String, byte[]> arrayMap = ArrayListMultimap.create();
arrayMap.put("test", "hello".getBytes());
arrayMap.put("title", "meow".getBytes());
arrayMap.put("body", "A powerful tool for building web apps.".getBytes());
HttpEntity<Multimap<String, byte[]>> uploadEntity = new HttpEntity<>(arrayMap, headers);
ResponseEntity<String> response = rt.postForEntity(uri, uploadEntity, String.class);
System.out.println(response);
}
catch (HttpClientErrorException e)
{
/**
*
* If we get a HTTP Exception display the error message
*/
logger.error("error http client: " + e.getResponseBodyAsString());
}
catch(Exception e)
{
logger.error("error: " + e.getMessage());
}
This is my Backend-server controller where it recevies the incoming data from my frontend-server.
import com.google.common.collect.Multimap;
...
@PostMapping(path="/rh2lev", consumes = "application/json", produces = "application/json")
public String setup(@RequestBody Multimap<String, byte[]> uploadIndex)
{
System.out.println(uploadIndex);
return "everything ok";
}
It seems that this error occurs on serializing Multimap
objects into JSON string or deserializing JSON string into Multimap
objects. Spring usually does JSON serialization/deserialization by using Jackson ObjectMapper
. Jackson ObjectMapper
can do JSON serialization/deserialization of java.util.Map
objects by default but can't com.google.common.collect.Multimap
objects.
So you need to configure a custom serializer in 'frontend-server' and also configure a custom deserializer in 'backend-server'. I think you can achieve this by using jackson-datatype-guava.
Example
Configurations for your 'frontend-server' and 'backend-server'
(pom.xml)
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-guava</artifactId>
</dependency>
(Spring Boot's configuration)
@Configuration
public class MyConfigurer {
@Bean
public Jackson2ObjectMapperBuilderCustomizer guavaModuleCustomizer() {
return builder -> {
builder.modules(new GuavaModule());
};
}
}
Related Question
Spring MVC mapping Guava Multimap
For More Information
“How-to” Guides 4.3. Customize the Jackson ObjectMapper - Spring Boot Reference Documentation
Intro to the Jackson ObjectMapper - Baeldung blog post
Jackson – Custom Serializer - Baeldung blog post
Getting Started with Custom Deserialization in Jackson - Baeldung blog post