-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Design for Enhance the ObjectMapper to support Spring Boot's pattern to enable autoconfiguration
This design is to make our current ObjectMapper could follow Spring Boot's configuration pattern.
Users now use MessageConverters with the default ObjectMapper which was newed by us, and this ObjectMapper doesn't support Spring Boot's configuration.
@Bean
@ConditionalOnMissingBean
public EventHubsMessageConverter eventHubsMessageConverter() {
return new EventHubsMessageConverter();
}/**
* Construct the message converter with default {@code ObjectMapper}.
*/
public EventHubsMessageConverter() {
this(OBJECT_MAPPER);
}public final class ObjectMapperHolder {
private ObjectMapperHolder() {
}
public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
}So this design is to enhance the ObjectMapper to let users also can work with Spring Boot's pattern, such as:
- Configure properties
- Customize
Jackson2ObjectMapperBuilderCustomizer - Override
ObjectMapper/Jackson2ObjectMapperBuilder
Spring Boot uses the default ObjectMapper created by JacksonObjectMapperConfiguration in JacksonAutoConfiguration, the ObjectMapper will be created if there is no other ObjectMapper in the ApplicationContext.
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Jackson2ObjectMapperBuilder.class)
static class JacksonObjectMapperConfiguration {
@Bean
@Primary
@ConditionalOnMissingBean
ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
return builder.createXmlMapper(false).build();
}
}And next step confirmed that JacksonAutoConfiguration was packaged in maven spring-boot-autoconfigure. which already exists in spring-cloud-azure-autoconfigure .
For Spring-Boot 3.0.0 RC2 actuator endpoints:
Use the ObjectMapper builded by Jackson2ObjectMapperBuilder in JacksonEndpointAutoConfiguration.
@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(JacksonAutoConfiguration.class)
public class JacksonEndpointAutoConfiguration {
@Bean
@ConditionalOnProperty(name = "management.endpoints.jackson.isolated-object-mapper", matchIfMissing = true)
@ConditionalOnClass({ ObjectMapper.class, Jackson2ObjectMapperBuilder.class })
public EndpointObjectMapper endpointObjectMapper() {
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json()
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,
SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS)
.serializationInclusion(Include.NON_NULL).build();
return () -> objectMapper;
}
}For spring-data-commons:
Use the SpringBoot's default ObjectMapper in SpringDataWebConfiguration
ObjectMapper mapper = context.getBeanProvider(ObjectMapper.class).getIfUnique(ObjectMapper::new);For AWS: Same in S3AutoConfiguration.
@ConditionalOnMissingBean
@Bean
S3ObjectConverter s3ObjectConverter(Optional<ObjectMapper> objectMapper) {
return new Jackson2JsonS3ObjectConverter(objectMapper.orElseGet(ObjectMapper::new));
}For GCP: Same in PubSubJsonPayloadApplication
@Bean
public JacksonPubSubMessageConverter jacksonPubSubMessageConverter(ObjectMapper objectMapper) {
return new JacksonPubSubMessageConverter(objectMapper);
}For Alibaba:
Seems doesn't use SpringBoot's default ObjectMapper, for example: SentinelAutoConfiguration
@ConditionalOnClass(ObjectMapper.class)
@Configuration(proxyBeanMethods = false)
protected static class SentinelConverterConfiguration {
@Configuration(proxyBeanMethods = false)
protected static class SentinelJsonConfiguration {
private ObjectMapper objectMapper = new ObjectMapper();
public SentinelJsonConfiguration() {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
}
@Bean("sentinel-json-flow-converter")
public JsonConverter jsonFlowConverter() {
return new JsonConverter(objectMapper, FlowRule.class);
}
...-
Consider there will be some users may not want to use
ObjectMapperfrom Spring context, so we could add a property to control whether to use it:Property Name Default Value Description spring.cloud.azure.message-converter.isolated-object-mappertrueWhether to use an isolated object mapper to serialize/deserialize message in EventHubsMessageConverter/ServiceBusMessageConverter/StorageQueueMessageConverter. -
We could use two MessageConverter beans, one is using default
ObjectMapperfrom SpringBootJacksonAutoConfiguration, another is from ObjectMapperHolder:@Bean @ConditionalOnMissingBean @ConditionalOnProperty(value = "spring.cloud.azure.message-converter.isolated-object-mapper", havingValue = "true", matchIfMissing = true) EventHubsMessageConverter defaultEventHubsMessageConverter() { return new EventHubsMessageConverter(ObjectMapperHolder.OBJECT_MAPPER); } @Bean @ConditionalOnMissingBean @ConditionalOnProperty(value = "spring.cloud.azure.message-converter.isolated-object-mapper", havingValue = "false") EventHubsMessageConverter eventHubsMessageConverter(ObjectMapper objectMapper) { return new EventHubsMessageConverter(objectMapper); }
-
Add property info in
additional-spring-configuration-metadata.json.{ "name": "spring.cloud.azure.message-converter.isolated-object-mapper", "type": "java.lang.Boolean", "defaultValue": "true", "description": "Whether to use an isolated object mapper to serialize/deserialize message in EventHubsMessageConverter/ServiceBusMessageConverter/StorageQueueMessageConverter." }
Finally, after this design, users could use spring's way to configure ObjectMapper and converter message when setting the property as false, or users can use our old ObjectMapper with nothing to configure.
- we also consider whether to add more properties for each messageConverter, but it is relatively rare in terms of user usage scenarios and is a bit redundant in terms of design, so we won't use it at present.
- Frequently Asked Questions
- Azure Identity Examples
- Configuration
- Performance Tuning
- Android Support
- Unit Testing
- Test Proxy Migration
- Azure Json Migration
- New Checkstyle and Spotbugs pattern migration
- Protocol Methods
- TypeSpec-Java Quickstart
- Getting Started Guidance
- Adding a Module
- Building
- Writing Performance Tests
- Working with AutoRest
- Deprecation
- BOM guidelines
- Release process
- Access helpers