Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot parameterized configuration

I'm working with a Spring application that has configurations defined for every year in an application.properties file. Basically at this point it's a copy-paste job, just incrementing the pasted configuration by 1. We have an analogous copy-paste process in several classes with bean definitions for every year as well.

Because there's a requirement to be able to access things defined by previous years' configurations, I'm thinking it would be simpler to provide a property for the current year, then define all the beans with some sort of parameterized properties. I'm not finding a great way to do this, though. Currently we have:

application.properties:

year2020.datasource.jdbcUrl=jdbc:postgresql://${built.url.2020}:5432/db_name
year2020.datasource.username=some_username
year2020.datasource.password=some_password
year2020.datasource.driverClassName=org.postgresql.Driver
year2020.datasource.validationQuery=SELECT 1

# And multiple similar configs for other resources and previous years

And some classes for the beans:

@Configuration
public class CopyPastedDataSource {

    @Bean(name = "year2020_datasource")
    @ConfigurationProperties(prefix = "year2020.datasource")
    public DataSource dataSource2020() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "year2019_datasource")
    @ConfigurationProperties(prefix = "year2019.datasource")
    public DataSource dataSource2020() {
        return DataSourceBuilder.create().build();
    }

    // And more beans for previous years
}

I was thinking maybe just replacing the year with a placeholder and replacing it with a year as needed at runtime. Is there a way to achieve this that would be more idiomatic or maintainable?

like image 976
aaaaaaaaaaaaaaaaaaaaaaa0983280 Avatar asked Feb 10 '26 04:02

aaaaaaaaaaaaaaaaaaaaaaa0983280


1 Answers

So it turns out I was looking for exactly this approach:

https://stackoverflow.com/a/26276872/7660079

https://stackoverflow.com/a/53554102/7660079

Instead of autowiring individual resources one by one and then collecting them into a single bean, you can autowire properties into a Map pretty easily. Here's an example from our list of similarly numbered API endpoints:

application.properties

api.url.2020=api-2020.endpoint.com
api.url.2019=api-2019.endpoint.com
api.url.2018=api-2018.endpoint.com

Bean:

@Configuration
@EnableConfigurationProperties

public class ApiConfiguration {
    @Bean
    @ConfigurationProperties(prefix = "api.url")
    public Map<Integer, String> getConfiguration() {
        return new HashMap<>();
    }
}

Autowired bean:

@Component
class APIConsumer {
    @Autowired
    Map<Integer, String> apiUrlsByYear;
}
like image 121
aaaaaaaaaaaaaaaaaaaaaaa0983280 Avatar answered Feb 13 '26 01:02

aaaaaaaaaaaaaaaaaaaaaaa0983280