spring-boot: @ConfigurationProperties does not work correctly after Spring Boot v3.0.x (Kotlin v1.7.x +Spring Boot v3.0.4)

Hi All, I am trying to connect multi datasources in my web application with Spring Boot v3.0.4. However, as I ran my web application the error below occurred.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flyway' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: 
Failed to instantiate [org.flywaydb.core.Flyway]: 
Factory method 'flyway' threw exception with message: Error creating bean with name 'routingDataSource' defined in class path resource [CouponDbConfig.class]: 
Failed to instantiate [javax.sql.DataSource]: 
Factory method 'routingDataSource' threw exception with message: dataSource or dataSourceClassName or jdbcUrl is required.

This is my source code.

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.coupon.writer")
    fun couponDatasourceWriter(): DataSource = DataSourceBuilder.create().build()
   // ...

    @FlywayDataSource
    @Bean
    fun routingDataSource(): DataSource {
        val writerDataSource: DataSource = couponDatasourceWriter()
    //...
   }

And here is my application.yml file.

spring:
  datasource:
    coupon:
      writer:
        driver-class-name: org.postgresql.Driver
        jdbc-url: jdbc:postgresql://localhost:xxx/test
        username: xxx 
        password: xxx

At first, I suspected that @ConfigurationProperties annotation cannot inject my application properties(myapplication.yml). So, I tested with the below code and the application can be run successfully.

    @Bean
    fun couponDatasourceWriter(): DataSource = DataSourceBuilder.create()
        .driverClassName("org.postgresql.Driver")
        .url("jdbc:postgresql://localhost:xxx/test")
        .username("xxx")
        .password("xxx")
        .build()
   // ...

    @FlywayDataSource
    @Bean
    fun routingDataSource(): DataSource {
        val writerDataSource: DataSource = couponDatasourceWriter()
    //...
   }

The thing is that in Spring Boot v2.6.6 the above code which error had occurred has been worked successfully without an issue. I think there might be a problem on Spring Boot v3.0.x version on its own. I found some issues regarding @ConfigurationProperties annotation with Spring Boot v3.0.x not exactly the same but the similar one. Could you all check this issue?

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 15 (5 by maintainers)

Most upvoted comments

@philwebb I found an issue today related to this bug.

I have a property that is set to true by default. I am overriding this value to false in the properties.yml file.

I dug a bit and found the binder.bind(bean) is returning the bean with the appropriate value which is false. However, the original bean is not updated and the registered bean is not updated too.

I can’t share the code but I added a screenshot. As you can see, the instance of the original bean and the bean returned by the binder are not the same.

Screenshot 2023-04-13 at 15 37 04

I did a test with two different ways to initialize the ConfigurationProperties. As you can see, the one defined with a @Bean function doesn’t work.

Where application.yml

security.token.validation.application.required: true

And TokenValidationConfig.kt


@ConfigurationProperties(prefix = "security.token.validation")
data class CustomEGTokenValidationSettings constructor(
    var application: JWKValidationConfig = JWKValidationConfig()
)

data class JWKValidationConfig(
    var required: Boolean = true
)

@Configuration
@EnableConfigurationProperties(CustomEGTokenValidationSettings::class)
class TokenValidationConfig {

    @Autowired
    private lateinit var customEGTokenValidationSettings: CustomEGTokenValidationSettings

    @Bean
    @ConfigurationProperties(prefix = "security.token.validation")
    fun issueCustomEGTokenValidationSettings() = CustomEGTokenValidationSettings()

    @Bean
    fun commandLineRunner(issueCustomEGTokenValidationSettings: CustomEGTokenValidationSettings) = CommandLineRunner {
        println(issueCustomEGTokenValidationSettings) // CustomEGTokenValidationSettings(application=JWKValidationConfig(required=true))
        println(customEGTokenValidationSettings) // CustomEGTokenValidationSettings(application=JWKValidationConfig(required=false))
    }
}




@AnneMayor Could you please attach the project as a zip file or share a GitHub repository.

From the snippet you’ve included it appears that DataSourceBuilder.create().build() is being used to create the DataSource which you then expect configuration properties to be applied to. I’m surprised that worked in 2.6.

I’d recommend changing your @Configuration so that you inject DataSourceProperties and use them to create the builder. You can find an example in https://docs.spring.io/spring-boot/docs/3.0.x/reference/htmlsingle/#howto.data-access.configure-two-datasources.

If that doesn’t work for you, could you please provide a sample application that works in 2.7 but fails in 3.0.