spring-cloud / spring-cloud/spring-cloud-commons
Properties not resolved on FactoryBean initialization for beans defined in XML
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 751
- Forks
- 744
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 9
Description
Describe the bug
Spring Cloud Commons: 4.0.0
Spring Boot: 3.0.1
This issue is strictly related to: https://github.com/spring-cloud/spring-cloud-commons/issues/439 and https://github.com/spring-cloud/spring-cloud-config/issues/1167
I've been using the Spring Cloud to connect to a config server on PCF, unfortunately it is some legacy code with beans declared in old-XML fashion way. We have theorg.springframework.transaction.interceptor.TransactionProxyFactoryBean as an abstract bean (defined in beans.xml file) which is parent to couple of specific bean instances. One of them does not contain the class attribute in definition. All of these instances contains transactionManager which has the sessionFactory which has our OracleDataSource class as property. The last one needs username/password/url to be properly initialized. They should be resolved from application.yml file.
Everything was working correctly until we migrated to the PCF. For some reason the SpringBoot started to throw the BeanCreationException:
Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is java.sql.SQLException: Invalid Oracle URL specified: OracleDataSource.makeURL
This URL is indeed null.
It is caused by calling this instruction: https://github.com/spring-cloud/spring-cloud-commons/blob/097959a64af4d4c1a3a45c90d150ea2455d817dd/spring-cloud-context/src/main/java/org/springframework/cloud/autoconfigure/RefreshAutoConfiguration.java#L231
it starts the cascade of bean creation if it cannot predict type or the type is assignable to FactoryBean.
It turned out the the DefaultListableBeanFactory used here does not have properly initialized properties (or PostProcessors?)
To wrap it up: it can happen only if:
- we have the spring-cloud enabled
- the bean is defined in XML without the class attribute
- the bean implements
org.springframework.beans.factory.FactoryBean<>interface
The simplest workaround is just defining the missing attribute but since it is not required by default I consider it as a bug.
Sample
The complete application to recreate this issue:
https://github.com/krysz/spring-cloud-commons-xml-bug
It contains BaseBean which is the instance of FactoryBean, the ChildBean defined in XML without class attribute and the DataSource bean with injected property. If you disable spring-cloud or add the class attribute the whole application runs fine and prints 42 as property value but with my provided configuration it fails with error: Caused by: java.lang.InstantiationException: Could not initialize dataSource with someProperty!
I think @D0rmouse correctly identified the root cause of it:
They fixed a initialization cascade, but the log from the demo project shows that the properties are loaded and should be resolvable when the FactoryBean is initialized.
And he also proposed the solution:
I would say you first load the properties and then instantiate any FactoryBeans that require properties, or not even load any FactoryBeans before loading the properties. The latter is probably not possible, because FactoryBeans are involved in loading properties.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the failure with the linked spring-cloud-commons-xml-bug sample, focusing on the XML ChildBean without a class attribute and its injected DataSource property. Read RefreshAutoConfiguration.java around line 231 and trace the FactoryBean initialization cascade. Done means the sample resolves the configured property and prints 42 without requiring the missing class attribute.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring, spring-boot
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100