Description
Problem:
I want to define my own ObjectMapper
as a bean (as it needs to be injected with other dependencies) without suddenly breaking the rest of my application.
@Bean("my-object-mapper")
@Qualifier("my-object-mapper")
public ObjectMapper flowObjectMapper(RequiredDependencies etc) { ... }
This unfortunately breaks the rest of the application. Despite giving it a name that nobody else uses, a Qualifier
that nobody else knows about, things like Feign, RabbitListeners, etc. suddenly start using this completely differently configured ObjectMapper
as their own. Why? Because JacksonAutoConfiguration
decides not to configure the default primary bean because ConditionalOnMissingBean
thinks that a bean with the correct type (not name, not qualifier) should match. This results in some completely randomly configured bean that was clearly not intended to be used for anything but a specific purpose (hence the name and qualifier) is suddenly used as the default globally for everything.
Would it not have made more sense to still create this Primary
bean if there is no suitable candidate which is unqualified and/or has the correct bean name?
Work-arounds:
-
Define your own
Primary
ObjectMapper
. Problem: how do I know how the Spring default one was configured? I suppose I could copy the source code if that doesn't change too often...builder.createXmlMapper(false).build()
-- poor solution IMHO. -
Subclass
ObjectMapper
so Spring's type matching doesn't mistake my custom mapper as something it can use... won't work most likely, as it is still anObjectMaper
... so wrap it then and delegate... ouch. -
Complicated stuff to register my bean as a non-primary bean using a
BeanFactoryPostProcessor
. Seriously?
Possible solutions that would work for me:
-
Allow a non-primary bean to be defined easily.
@Bean(primary = false)
or@Bean(cannotBeUsedUnqualified = true)
-
Introduce a
ConditionalOnMissingUnqualifiedBean
and use that inJacksonAutoConfiguration
. Probably not backwards compatible.