Currently using Spring Boot 3.1 with the reactive WebClient configured like this:
@Configuration
public class MyConfig {
@Bean
WebClient webClient() {
ExchangeStrategies strategies = ExchangeStrategies.builder().codecs(clientCodecConfigurer ->
{
ObjectMapper objectMapper = createObjectMapper();
Jackson2JsonDecoder decoder = new Jackson2JsonDecoder(objectMapper);
decoder.setMaxInMemorySize(10_000_000);
clientCodecConfigurer.customCodecs().register(decoder);
clientCodecConfigurer.customCodecs().register(new Jackson2JsonEncoder(objectMapper));
}
).build();
return WebClient.builder()
.exchangeStrategies(strategies)
.baseUrl(this.properties.baseUrl())
.build();
}
@Bean
public HttpServiceProxyFactory httpServiceProxyFactory(
WebClient webClient) {
return HttpServiceProxyFactory
.builder(WebClientAdapter.forClient(webClient))
.build();
}
@Bean
public MyRemoteServiceApi myGateway(HttpServiceProxyFactory httpServiceProxyFactory) {
return httpServiceProxyFactory.create(MyRemoteServiceApi.class);
}
private static ObjectMapper createObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.KEBAB_CASE);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.setSerializationInclusion(Include.NON_NULL);
mapper.registerModule(new JavaTimeModule());
return mapper;
}
}
I am using 2 customizations:
How can I migrate this code to use the RestClient of Spring Boot 3.2?
For the custom object mapper, I now have done this:
@Bean
public RestClient restClient() {
return RestClient.builder()
.messageConverters(httpMessageConverters -> {
httpMessageConverters.clear();
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(createObjectMapper());
httpMessageConverters.add(converter);
})
.baseUrl(this.properties.baseUrl())
.build();
}
This seems to work, but I find it strange I have to first clear the list. Is this really the way it should be done?
Second question: how do I set that maxInMemorySize? Or is that not needed with RestClient?
A cleaner alternative to walrus03's answer:
RestClient.Builder restClientBuilder = RestClient.builder();
restClientBuilder.messageConverters(c -> {
// Remove any existing MappingJackson2HttpMessageConverter
c.removeIf(MappingJackson2HttpMessageConverter.class::isInstance);
// Add MappingJackson2HttpMessageConverter
c.add(new MappingJackson2HttpMessageConverter(newObjectMapper));
});
This is how we have done it (It's a kotlin code):
RestClient.builder()
.messageConverters { messageConverters ->
val newConverters = messageConverters.map { converter ->
if (converter is MappingJackson2HttpMessageConverter) {
val newObjectMapper = createObjectMapper()
MappingJackson2HttpMessageConverter(newObjectMapper)
} else {
converter
}
}
messageConverters.clear()
newConverters.forEach { messageConverters.add(it) }
}
By doing like that, you can preserve other converters initialized by Spring by default, andupdate only MappingJackson2HttpMessageConverter ones.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With