MessageSourceAutoConfiguration provides configuration of a ResourceBundleMessageSource in case a resource bundle is present and no other MessageSource bean is already configured. However, in some cases a different subclass of AbstractResourceBasedMessageSource needs to be used in a Spring Boot application. For example, ReloadableResourceBundleMessageSource, or in our case a custom one with special handling of message arguments of a certain type.

While it is easy to define your own MessageSource bean which will override the auto-configuration, this has the drawback that automatic property configuration of the message source by using "spring.messages"-prefixed application properties is also lost.

MessageSourceAutoConfiguration currently calls the ResourceBundleMessageSource() constructor directly. All the methods that are then called on this message source are present on AbstractResourceBasedMessageSource. It would be convenient if we could configure a provider for AbstractResourceBasedMessageSource which would override an auto-configured one that instantiates ResourceBundleMessageSource directly, and which would then be further automatically configured using the "spring.messages"-prefixed application properties.

Comment From: wilkinsona

Thanks for the suggestion.

Generally speaking we try to make each @Bean method in our auto-configuration return the most specific type possible. While the bean named messageSource is a special case as AbstractApplicationContext looks it up by name, the current inconsistency is a little awkward and I would prefer it if the method's return type was ResourceBundleMessageSource.

Changing the return type to ResourceBundleMessageSource would make it impossible to implement your provider suggestion. However, that approach would, I think, be unique in the code base as I can't think of anywhere else where we have a @Bean method that allows the type that it returns to be customized in that way.

If we want to make it easier to create a custom AbstractResourceBasedMessageSource subclass using MessageSourceProperties, I think we would be better pulling out the code that configures the message source into a separate reusable class. However, this would be a step towards this change which we have decided that we do not want to pursue at this time.

Flagging for team attention so that we can discuss what, if anything, we want to do here.

Comment From: wilkinsona

We'd like to consider this in a broader context. There are other places where it may be useful to allow Boot's @ConfigurationProperties to be mapped onto a user-provided bean that's replacing one that would normally be auto-configured. In the meantime, we recommend configuring the bean manually and, if you want to keep the existing spring.messages-based configuration, copy-pasting the existing code that maps the properties onto the message source.

Comment From: HermanBovens

Thanks for giving this attention.

I'm not 100% convinced that returning the most specific type possible is in all cases the best option, as you don't always want people to rely on getting a particular implementation injected.

Maybe it's also an opportunity to think about standard/preferred ways to make things configurable.

In the case of the Jackson ObjectMapper customization, there are properties (1st level), creating additional beans of type Jackson2ObjectMapperBuilderCustomizer or adding beans of type com.fasterxml.jackson.databind.Module (2nd level), overriding of auto-configured Jackson2ObjectMapperBuilder (3rd level), or even directly replacing the auto-configured ObjectMapper (4th level). If ObjectMapper were an interface or abstract class, and certain features required a specific implementation to be used, another mechanism would be needed because otherwise the user would have to override the auto-configured Jackson2ObjectMapperBuilder, thereby losing the property-based configuration provided by StandardJackson2ObjectMapperBuilderCustomizer. And if the return type of the auto-configured mapper would be a specific subtype, even the whole mapper would have to be replaced instead of just the builder.