0
@Singleton
public class TestFunction extends FunctionInitializer {
    Logger log = LoggerFactory.getLogger(TestFunction.class);

    public TestFunction() {
    }

    public String execute() {
        return "Hello";
    }

}

I want to override datasource properties in application.yml file programmatically, but without using bean created event listener. Is there a way to do that. Like creating a custom application context with properties.

I have used the below approach for Micronaut API gateway proxy.

public class StreamLambdaHandler implements RequestStreamHandler {
.......
public StreamLambdaHandler() {
        try {
            log.info("Initializing Lambda Container");
            this.dbCredentialService = new DBCredentialService();
            // Get updated database credential map
            Map<String, Object> props = this.dbCredentialService.getDbCredential();
            // Create application context builder with updated properties
            // i.e Override datasources properties in application.yml
            builder = ApplicationContext.build().properties(props);
            handler = new MicronautLambdaContainerHandler(builder);
      }....
    ........
}

Can we do something similar with FunctionInitializer?

Sujith C P
  • 105
  • 1
  • 11
  • "I want to override datasource properties in application.yml file programmatically..." - From where do you want to get the new values that override the values defined in `application.yml`? Knowing where the info will come from will help identify a good solution. – Jeff Scott Brown Aug 04 '20 at 13:24
  • I believe you need factory where you tell the bean how it is created https://docs.micronaut.io/latest/api/io/micronaut/context/annotation/Factory.html Are you able to provide a more accurate example what exactly you plan to override ? – Traycho Ivanov Aug 04 '20 at 14:33
  • "I believe you need factory where you tell the bean how it is created" - You don't necessarily need a factory where you tell the bean how it is created. There are numerous ways to override values that would otherwise have come from `application.yml`. Knowing where the data is coming from at runtime will help identify a good solution. – Jeff Scott Brown Aug 04 '20 at 19:10
  • @JeffScottBrown Hi, I want to fetch database credentials from secrets manager and use it for Hibernate/Hikari. – Sujith C P Aug 05 '20 at 04:44
  • @Traycho Ivanov As metioned in the previous comment, I have to read some secrets values from AWS secrets manager and use it to bootstrap Hibernate. – Sujith C P Aug 05 '20 at 04:48

1 Answers1

1

If you plan to override only datasource credentials properties it could be done this way.

@Factory
public class HikariDataSourceFactory {

    @Bean
    @Primary
    public DataSource dataSource(DBCredentialService credentialService) throws URISyntaxException {

        Map<String, Object> credentials = this.dbCredentialService.getDbCredential();
        String username = "user";
        String password = credentials.get("username");  
        
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:postgresql://localhost:5432/postgres");
        config.setUsername(username);
        config.setPassword(password);
        config.setDriverClassName("org.postgresql.Driver");

        return new HikariUrlDataSource(config);
    }
}
Traycho Ivanov
  • 2,887
  • 14
  • 24
  • It is helpful. Is there any way to override only some properties (say password) while the other properties being read from the application.yml itself? Or in a wider scope, not only datasource properties but override a subset of properties in the application.yml – Sujith C P Aug 05 '20 at 09:22
  • @SujithCP You could have own `PropertySourceLoader`, check extending `AbstractPropertySourceLoader` and define order so it takes your expected priority. – Traycho Ivanov Aug 05 '20 at 17:38