Browse Source

Document HttpMessageConverters detection changes

This commit updates the reference documentation to better reflect
changes applied in gh-48310. As of Spring Boot 4.0.1,
`HttpMessageConverter` beans are all considered as "custom" converters
and will be set ahead of the converters list in the auto-configuration
support.

For more specific changes, developers should contribute
`ClientHttpMessageConvertersCustomizer` or
`ServerHttpMessageConvertersCustomizer` beans to better reflect their
intent: should the converter be configured for client, server or both?
How should this converter be used?

Previously, Spring Boot was relying on heuristics but they would cause
issues for server-only converters, or for specific configuration that
were not meant to replace the default converter for a given media type.

Closes gh-48574
pull/48578/head
Brian Clozel 4 months ago
parent
commit
f61ac29f3f
  1. 5
      documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/web/servlet.adoc
  2. 36
      documentation/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/servlet/springmvc/messageconverters/MyHttpMessageConvertersConfiguration.java
  3. 25
      documentation/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/servlet/springmvc/messageconverters/MyHttpMessageConvertersConfiguration.kt

5
documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/web/servlet.adoc

@ -98,7 +98,10 @@ Any javadoc:org.springframework.http.converter.HttpMessageConverter[] bean that @@ -98,7 +98,10 @@ Any javadoc:org.springframework.http.converter.HttpMessageConverter[] bean that
You can also override default converters in the same way.
If you need to add or customize converters, you can declare one or more javadoc:org.springframework.boot.http.converter.autoconfigure.ClientHttpMessageConvertersCustomizer[] or
javadoc:org.springframework.boot.http.converter.autoconfigure.ServerHttpMessageConvertersCustomizer[] as beans, as shown in the following listing:
javadoc:org.springframework.boot.http.converter.autoconfigure.ServerHttpMessageConvertersCustomizer[] as beans. There, you can choose whether converter instances should be added
before default ones (`addCustomConverter`) or if they should override a specific default converter (like `withJsonConverter`).
See the following listing for an example:
include-code::MyHttpMessageConvertersConfiguration[]

36
documentation/spring-boot-docs/src/main/java/org/springframework/boot/docs/web/servlet/springmvc/messageconverters/MyHttpMessageConvertersConfiguration.java

@ -16,9 +16,17 @@ @@ -16,9 +16,17 @@
package org.springframework.boot.docs.web.servlet.springmvc.messageconverters;
import java.text.SimpleDateFormat;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.boot.http.converter.autoconfigure.ClientHttpMessageConvertersCustomizer;
import org.springframework.boot.http.converter.autoconfigure.ServerHttpMessageConvertersCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverters.ClientBuilder;
import org.springframework.http.converter.HttpMessageConverters.ServerBuilder;
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
@Configuration(proxyBeanMethods = false)
public class MyHttpMessageConvertersConfiguration {
@ -29,4 +37,32 @@ public class MyHttpMessageConvertersConfiguration { @@ -29,4 +37,32 @@ public class MyHttpMessageConvertersConfiguration {
.addCustomConverter(new AnotherHttpMessageConverter());
}
@Bean
public JacksonConverterCustomizer jacksonConverterCustomizer() {
JsonMapper jsonMapper = JsonMapper.builder().defaultDateFormat(new SimpleDateFormat("yyyy-MM")).build();
return new JacksonConverterCustomizer(jsonMapper);
}
// contribute a custom JSON converter to both client and server
static class JacksonConverterCustomizer
implements ClientHttpMessageConvertersCustomizer, ServerHttpMessageConvertersCustomizer {
private final JsonMapper jsonMapper;
JacksonConverterCustomizer(JsonMapper jsonMapper) {
this.jsonMapper = jsonMapper;
}
@Override
public void customize(ClientBuilder builder) {
builder.withJsonConverter(new JacksonJsonHttpMessageConverter(this.jsonMapper));
}
@Override
public void customize(ServerBuilder builder) {
builder.withJsonConverter(new JacksonJsonHttpMessageConverter(this.jsonMapper));
}
}
}

25
documentation/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/web/servlet/springmvc/messageconverters/MyHttpMessageConvertersConfiguration.kt

@ -17,9 +17,13 @@ @@ -17,9 +17,13 @@
package org.springframework.boot.docs.web.servlet.springmvc.messageconverters
import org.springframework.boot.http.converter.autoconfigure.ClientHttpMessageConvertersCustomizer
import org.springframework.boot.http.converter.autoconfigure.ServerHttpMessageConvertersCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.converter.HttpMessageConverters
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter
import tools.jackson.databind.json.JsonMapper
import java.text.SimpleDateFormat
@Configuration(proxyBeanMethods = false)
class MyHttpMessageConvertersConfiguration {
@ -33,5 +37,26 @@ class MyHttpMessageConvertersConfiguration { @@ -33,5 +37,26 @@ class MyHttpMessageConvertersConfiguration {
}
}
@Bean
fun jacksonConverterCustomizer(): JacksonConverterCustomizer {
val jsonMapper = JsonMapper.builder()
.defaultDateFormat(SimpleDateFormat("yyyy-MM"))
.build()
return JacksonConverterCustomizer(jsonMapper)
}
// contribute a custom JSON converter to both client and server
class JacksonConverterCustomizer(private val jsonMapper: JsonMapper) :
ClientHttpMessageConvertersCustomizer, ServerHttpMessageConvertersCustomizer {
override fun customize(builder: HttpMessageConverters.ClientBuilder) {
builder.withJsonConverter(JacksonJsonHttpMessageConverter(this.jsonMapper))
}
override fun customize(builder: HttpMessageConverters.ServerBuilder) {
builder.withJsonConverter(JacksonJsonHttpMessageConverter(this.jsonMapper))
}
}
}

Loading…
Cancel
Save