Spring RestTemplate message converter priority when posting
Asked Answered
L

2

13

What is the most convenient way to influence the priority of the message converters Spring applies when POSTing with RestTemplate?

Use case: I want to ensure a given entity is POSTed as JSON rather than e.g. XML when I do restTemplate.postForEntity(url, entity, Void.class).

Default

By default the entity is converted to XML because the MappingJackson2XmlHttpMessageConverter takes precedence over the MappingJackson2HttpMessageConverter. The default list of converters for my app appears to be (Spring scans the classpath to see what's available): enter image description here

Option 1

You can configure the message converters explicitly for a given RestTemplate instance like so restTemplate.setMessageConverters(Lists.newArrayList(new MappingJackson2HttpMessageConverter())). This is inconvenient if the instance is shared (as a Spring bean for example) as you might need converter X in one case and converter Y in a different one.

Option 2

You can set Accept and Content-Type HTTP headers explicitly in which case Spring will use a matching message converter. The downside is that you have to resort to RestTemplate.exchange instead of RestTemplate.postForEntity which means: extra code, less convenience.

HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
requestHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
HttpEntity requestEntity = new HttpEntity(entity, requestHeaders);
restTemplate.exchange(url, HttpMethod.POST, requestEntity, Void.class);

Option 3

This might be what I'm looking for :)

Landtag answered 19/12, 2017 at 20:21 Comment(0)
D
1

According to the Spring javadoc (https://docs.spring.io/spring-framework/docs/current/javadoc-api/index.html?org/springframework/web/client/RestTemplate.html) you can still use postForEntity,

public <T> ResponseEntity<T> postForEntity(java.lang.String url,
                                       @Nullable
                                       java.lang.Object request,
                                       java.lang.Class<T> responseType,
                                       java.util.Map<java.lang.String,?> uriVariables)
                                throws RestClientException
....

The request parameter can be a HttpEntity in order to add additional HTTP headers to the request.

Dement answered 24/4, 2018 at 20:8 Comment(0)
O
3

This issue is answered in detail here.

Basically, when you add the below-mentioned library, it adds MappingJackson2XmlHttpMessageConverter before MappingJackson2HttpMessageConverter. As a result, Spring boot assumes every request accepts application/XML.

 <dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

To avoid this behaviour, you might want to swap the two message converters.

Example:

  @Bean
RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
// move XML converter to the end of list
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
for (int i = 0; i < messageConverters.size() -1 ; i++) {
    if (messageConverters.get(i) instanceof MappingJackson2XmlHttpMessageConverter) {
        Collections.swap(messageConverters, i,messageConverters.size() - 1);
    }
}

restTemplate.setMessageConverters(messageConverters);

// add interceptors if necessary
restTemplate.setInterceptors(Collections.singletonList(catalogInterceptior()));
return restTemplate;

}

Oxbow answered 6/8, 2021 at 14:53 Comment(0)
D
1

According to the Spring javadoc (https://docs.spring.io/spring-framework/docs/current/javadoc-api/index.html?org/springframework/web/client/RestTemplate.html) you can still use postForEntity,

public <T> ResponseEntity<T> postForEntity(java.lang.String url,
                                       @Nullable
                                       java.lang.Object request,
                                       java.lang.Class<T> responseType,
                                       java.util.Map<java.lang.String,?> uriVariables)
                                throws RestClientException
....

The request parameter can be a HttpEntity in order to add additional HTTP headers to the request.

Dement answered 24/4, 2018 at 20:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.