Change runtime data source url in spring

I have a spring application configured with annotations. Here is part of my configuration

@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 an 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 the user selects another server to connect to us, we set the system property and the closed application context and update

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

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

  • why doesn't it work now?
  • How to get rid of setting the host name through the system property in general?

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

+4
source share
1 answer

not sure why it doesn't work, but you can try to do a couple more things:

  • Is closing the context before the update is really necessary? Try updating it.
  • You can mark your bean as @RefreshScope (but it requires the spring cloud) and update it with the /refresh endpoint. This will require the other endpoint to actually update your host on the bean before invoking the update.

"how to get rid of setting the hostname through the system property in general?"

pass this to the properties file, which is usually configured. If you use spring boot, you only need to configure:

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

properties. A datasource bean will be created using these values ​​for you.

0
source

All Articles