简体   繁体   中英

change datasource url at runtime in spring

I have spring application configured via annotations. Here is part of my config

@Configuration
@EnableTransactionManagement
public class JpaSpringConfiguration {

    @Bean(destroyMethod = "close")
    @Lazy
    @Primary
    public BasicDataSource dataSource(@Value("${statistics.hostname}") String statisticsHostname) { 
        final BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("org.postgresql.Driver");
        String url = String.format("jdbc:postgresql://%s:5432/statistics-db", statisticsHostname);
        dataSource.setUrl(url);
        ....
        return dataSource;
    }

    @Bean
    public static PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() {
        final PropertyPlaceholderConfigurer placeholderConfigurer = new PropertyPlaceholderConfigurer();
        placeholderConfigurer.setSystemPropertiesMode(SYSTEM_PROPERTIES_MODE_OVERRIDE);
        Properties properties = new Properties();
        properties.setProperty("statistics.hostname", "localhost");

        placeholderConfigurer.setProperties(properties);
        return placeholderConfigurer;
    }

Until recently we had xml configuration

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    <property name="properties">
        <props>
            <prop key="statistics.hostname">localhost</prop>
        </props>
    </property>
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" lazy-init="true" destroy-method="close">
    <property name="driverClassName" value="org.postgresql.Driver" />
    <property name="url" value="jdbc:postgresql://${statistics.hostname}:5432/statistics-db" />
    <property name="username" value="user" />
    <property name="password" value="password" />
</bean>

When user selected different server to connect to we set system property and closed application context and refreshed

System.setProperty("statistics.hostname", hostname)
applicationContext.close()
applicationContext.refresh()

This does not work when I use annotation configuration. My questions are:

  1. why it does not work now?
  2. how to get rid of setting hostname via system property altogether?

EDIT: I just found out that I forgot ${} around the name of the parameter in method dataSource(). So it works now but question 2 still remains.

not sure why it doesnt work, but you may try to do couple more things:

  1. Is closing context before refresh really needed? Try to only refresh it.
  2. You can mark your bean as @RefreshScope ( but it requires spring cloud ) and refresh it using /refresh endpoint. That would require another endpoint to actually update your host on a bean before calling refresh.

"how to get rid of setting hostname via system property altogether?"

pass that to property file which is the way it is normally configured. If you are using spring boot, then you only have to configure:

spring.datasource.url=
spring.datasource.username=
spring.datasource.password=
...

properties. Datasource bean would be created using those values for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM