Reputation: 92437
I have a custom StringToBooleanConverter
that should replace the default converter coming with Spring. So the source and target types are exactly the same. But instead of replacing the existing Spring converter, my converter is added. If I debug the application, I can see both converters in the same map entry of the Map
ConversionService#converters.
The ConversionService is configured like this:
@Bean
open fun conversionService(converters: Set<Converter<*, *>>) =
ConversionServiceFactoryBean().apply { setConverters(converters) }
@Bean
open fun stringToBooleanConverter() = MyStringToBooleanConverter()
// some more converters not relevant here ...
The problem is that sometimes the wrong converters gets used.
How can I remove/replace/hide/deactivate the converter delivered by Spring?
Upvotes: 4
Views: 1736
Reputation: 92437
The trick is to define a custom ConversionServiceFactoryBean
, to override the method createConversionService
, and to remove the StringToBooleanConverter
registered by Spring itself:
class ConversionServiceFactoryWithoutStringToBooleanConverter : ConversionServiceFactoryBean() {
override fun createConversionService(): GenericConversionService {
val conversionService = super.createConversionService()
conversionService.removeConvertible(String::class.java, java.lang.Boolean::class.java)
return conversionService
}
}
However, in this case it is not necessary to remove the Spring converter because if there is more than one converter for a certain source and target type Spring tries them in order and converters registered by the user come first. The behavior that drove me to this investigation was in fact related to another bug not related to the ConversionService
.
Upvotes: 3
Reputation: 39294
Update
If you're running Spring Boot, you can start your application like this and get a bean as follows.
ApplicationContext ctx = SpringApplication.run(Main.class, args);
DispatcherServlet servlet = (DispatcherServlet)ctx.getBean("dispatcherServlet");
You can list all the beans with:
ctx.getBeanDefinitionNames()
Note that most are just named as the class name with a lower case first letter (would assume "stringToBooleanConverter" for you). Some have the package name in front and then that. You can check this out in a debugger easily :).
You can find a bean of a specific class type like this (note that this definition returns null in my case; so this dependency doesn't seem to be in my application):
ctx.getBean(StringToBooleanConverter.class)
You can remove the bean with:
((AnnotationConfigEmbeddedWebApplicationContext)
ctx).removeBeanDefinition("yourBeanName")
Original Suggestion
This ties into a related question here: https://stackoverflow.com/a/12447211/857994. as realistically, you just want to remove the existing bean.
You can get a reference to the bean factory and remove the old bean from it manually. I think the most direct method would probably be the one suggested in the comment though: "Just implement BeanFactoryAware and then cast BeanFactory with DefaultListableBeanFactory"
.
I don't believe there is a way to stop the provision of the bean in the first place since it comes from spring itself. You can annotate your own beans to avoid autowiring, I don't know how you could achieve that on a spring-provided bean though.
Upvotes: 0