is it possible to instantiate 2 beans of the same ...
# spring
v
is it possible to instantiate 2 beans of the same data class eg.
Copy code
@Configuration
class DataSourceConfig {

    companion object {
        private val logger = LoggerFactory.getLogger(DataSourceConfig::class.java)
    }

    @ConstructorBinding
    @ConfigurationProperties(prefix = "datasource.default")
    data class DefaultDataSource(
        val host: String,
        val port: Int,
        val database: String,
        val username: String,
        val password: String
    ) {
        init {
            <http://logger.info|logger.info>(toString())
        }
    }

    @ConstructorBinding
    @ConfigurationProperties(prefix = "datasource.write")
    data class WriteDataSource(
        val host: String,
        val port: Int,
        val database: String,
        val username: String,
        val password: String
    ) {
        init {
            <http://logger.info|logger.info>(toString())
        }
    }

    @Bean
    fun defaultFactory(defaultDataSource: DefaultDataSource): ConnectionFactory {
        return ConnectionFactories.get(
            ConnectionFactoryOptions.builder()
                .option(ConnectionFactoryOptions.DRIVER, "pool")
                .option(ConnectionFactoryOptions.PROTOCOL, "postgresql")
                .option(ConnectionFactoryOptions.HOST, defaultDataSource.host)
                .option(ConnectionFactoryOptions.PORT, defaultDataSource.port)
                .option(ConnectionFactoryOptions.USER, defaultDataSource.username)
                .option(ConnectionFactoryOptions.PASSWORD, defaultDataSource.password)
                .option(ConnectionFactoryOptions.DATABASE, defaultDataSource.database)
                .build()
        )
    }

    @Bean
    fun writeFactory(writeDataSource: WriteDataSource): ConnectionFactory {
        return ConnectionFactories.get(
            ConnectionFactoryOptions.builder()
                .option(ConnectionFactoryOptions.DRIVER, "pool")
                .option(
                    ConnectionFactoryOptions.PROTOCOL,
                    "postgresql"
                )
                .option(ConnectionFactoryOptions.HOST, writeDataSource.host)
                .option(ConnectionFactoryOptions.PORT, writeDataSource.port)
                .option(ConnectionFactoryOptions.USER, writeDataSource.username)
                .option(ConnectionFactoryOptions.PASSWORD, writeDataSource.password)
                .option(ConnectionFactoryOptions.DATABASE, writeDataSource.database)
                .build()
        )
    }


    @Bean
    @Primary
    fun databaseClient(@Qualifier("defaultFactory") connectionFactory: ConnectionFactory) =
        DatabaseClient.create(connectionFactory)


    @Bean
    fun writeDatabaseClient(@Qualifier("writeFactory") connectionFactory: ConnectionFactory) =
        DatabaseClient.create(connectionFactory)

}
Can I clean this up into something that scales when I need to coneect to multiple dbs
t
I'd say using jdbc uri is the simplest way to get rid of it. You could also extend from
data class DataSource
v
thanks, this is brilliant. I cleaned up using URL, but for the data class, I still have to write the params twice right, wonder if there is a way around that
t
You don't need that data class anymore.
v
Copy code
@Configuration
class DataSourceConfig {

    companion object {
        private val logger = LoggerFactory.getLogger(DataSourceConfig::class.java)
    }

    @ConstructorBinding
    @ConfigurationProperties(prefix = "datasource.default")
    data class DefaultDataSource(
        val url: String,
        val username: String,
        val password: String
    ) {
        init {
            <http://logger.info|logger.info>(toString())
        }
    }

    @ConstructorBinding
    @ConfigurationProperties(prefix = "datasource.write")
    data class WriteDataSource(
        val url: String,
        val username: String,
        val password: String
    ) {
        init {
            <http://logger.info|logger.info>(toString())
        }
    }

    @Bean
    fun defaultFactory(defaultDataSource: DefaultDataSource): ConnectionFactory {
        return ConnectionFactories.get(ConnectionFactoryOptions
            .parse(defaultDataSource.url)
            .mutate()
            .option(ConnectionFactoryOptions.USER, defaultDataSource.username)
            .option(ConnectionFactoryOptions.PASSWORD, defaultDataSource.password)
            .build())
    }
    @Bean
    fun writeFactory(writeDataSource: WriteDataSource): ConnectionFactory {
        return ConnectionFactories.get(ConnectionFactoryOptions
            .parse(writeDataSource.url)
            .mutate()
            .option(ConnectionFactoryOptions.USER, writeDataSource.username)
            .option(ConnectionFactoryOptions.PASSWORD, writeDataSource.password)
            .build())
    }

    @Bean
    @Primary
    fun databaseClient(@Qualifier("defaultFactory") connectionFactory: ConnectionFactory) =
        DatabaseClient.create(connectionFactory)


    @Bean
    fun writeDatabaseClient(@Qualifier("writeFactory") connectionFactory: ConnectionFactory) =
        DatabaseClient.create(connectionFactory)
This is what I have
t
username and password should also be in the url
username:password@host
v
Yeah I was hoping to avoid that since I wanted those to be read from env vars in spring haha
t
And what's the difference between adding these as another parameters or as part of the url?
v
currently we are persisting all user names and passwords as kube secrets, while putting the normal configs as kube config maps, mainly convention I guess
t
Well... extending these classes is what is left for you.
v
got it still eliminating the individual props certainly made it cleaner, thanks for the tip