Reputation: 2490
I am building a Spring Boot Rest API server to port a legacy application on a more robust framework. That is my first project using those technologies. So far I have built a proof of concept with 2 API that reply "Hello world!" in JSON. One is open and the other is secured with OAuth2. I am done tuning the security up to the requirement.
I have also built a strong test structure using a combination of Rest-Assured for integration tests and Spring MockMvc for unit tests, so I am confident I am ready to start implementing real API using a TDD approach.
We are using Maven. My problem is that as soon as I had a dependency with our existing artifacts, I get the following stack. I understand what it means but our codebase is huge and I can't find out where this comes from. When I ask Google about this problem, I often find result simply suggesting to add spring.main.allow-bean-definition-overriding=true
to my properties. Isn't this just sweeping the problem under the rug ? I would guess there is a very good reason why Spring doesn't allow this by default. What are the possible consequences of simply ignoring that error with a convenient application properties ?
The stack :
*************************** APPLICATION FAILED TO START
***************************
Description:
The bean 'org.springframework.transaction.config.internalTransactionAdvisor', defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class], could not be registered. A bean with that name has already been defined in null and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
[WARNING] java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:498)
at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run (AbstractRunMojo.java:558)
at java.lang.Thread.run (Thread.java:748) Caused by: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'org.springframework.transaction.config.internalTransactionAdvisor' defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration; factoryMethodName=transactionAdvisor; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class]] for bean 'org.springframework.transaction.config.internalTransactionAdvisor': There is already [Root bean: class [org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] bound.
at org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition (DefaultListableBeanFactory.java:897)
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod (ConfigurationClassBeanDefinitionReader.java:274)
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass (ConfigurationClassBeanDefinitionReader.java:141)
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions (ConfigurationClassBeanDefinitionReader.java:117)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions (ConfigurationClassPostProcessor.java:327)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry (ConfigurationClassPostProcessor.java:232)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors (PostProcessorRegistrationDelegate.java:275)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors (PostProcessorRegistrationDelegate.java:95)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors (AbstractApplicationContext.java:705)
at org.springframework.context.support.AbstractApplicationContext.refresh (AbstractApplicationContext.java:531)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh (ServletWebServerApplicationContext.java:142)
at org.springframework.boot.SpringApplication.refresh (SpringApplication.java:775)
at org.springframework.boot.SpringApplication.refreshContext (SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run (SpringApplication.java:316)
at org.springframework.boot.SpringApplication.run (SpringApplication.java:1260)
at org.springframework.boot.SpringApplication.run (SpringApplication.java:1248)
at ca.mycompany.oav.ResourceServerApplication.main (ResourceServerApplication.java:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:498)
at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run (AbstractRunMojo.java:558)
at java.lang.Thread.run (Thread.java:748)
Upvotes: 5
Views: 13001
Reputation: 3955
spring.main.allow-bean-definition-overriding=true
concerns overriding beans using the same bean name as an existing bean. If the bean is in your own code, you can always just change the bean name (if using @Bean
, the name is by default the method name, or the class name for @Component
; but there are different ways to set the bean name, check the docs).
So the only reasonable (as far as I can think) reason to set this flag is if multiple beans that you don't control (i.e. from 3rd party code) are loaded with the same name.
Upvotes: 1
Reputation: 1504
Answer is
No don't use overriding as much as possible. But at times may be (but with caution)
To understand this better,
When you start the Application, Spring Boot auto-loads many beans (to provide out-of-the-box functionalities) some may be required some may not be. There are two options we have
Option #1:
Option #2:
Spring Boot provides out of the box Cloud Configuration with ConfigServicePropertySourceLocator. in a realtime scenario, we will have our own secured config server to use instead of the default one.
Option #1:
spring.main.allow-bean-definition-overriding=true
Option #2:
spring.cloud.config.enabled=false
You save startup time also code looks clean.
Ref: https://github.com/spring-cloud/spring-cloud-config/issues/177
Upvotes: 0
Reputation: 2322
Just to be aware that: by adding this, it is difficult to guess which bean will have priority because the bean creation order is determined by dependency relationships mostly influenced in runtime. Therefore, allowing bean overriding can produce unexpected behavior unless we know the dependency hierarchy of our beans well enough.
Upvotes: 7