Reputation: 720
I am using springboot 2.0.4.RELEASE
and am trying to configure database properties for my app. I added a new configuration file as follows:
@Configuration
@ConfigurationProperties(prefix="spring.datasource")
public class DatabaseConfig
{
private String userName;
private String password;
public String getUserName() {
try {
userName = Files.readAllLines(Paths.get("/secrets/username.txt")).get(0);
} catch (IOException e) {
e.printStackTrace();
}
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
try {
password = Files.readAllLines(Paths.get("/secrets/password.txt")).get(0);
} catch (IOException e) {
e.printStackTrace();
}
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Here's my application.properties
spring.datasource.url=jdbc:sqlserver://mno35978487001.cloud.xyz.com:14481
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
spring.jpa.show-sql=true
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
I was hoping when the application runs, application.properties
will be able to read the user name and password from the file but that doesn't seem to happen. Any thoughts on what I am missing? Are there any better ways of reading those values and setting them dynamically?
Upvotes: 1
Views: 3646
Reputation: 2210
You can add custom property source locator.
https://source.coveo.com/2018/08/03/spring-boot-and-aws-parameter-store/
Basically, you need
public class SecretStorePropertySource extends PropertySource<SecretStoreSource> {
public SecretStorePropertySource(String name) {
super(name);
}
@Override
public Object getProperty(String name) {
if (name.startsWith("secrets.")) {
// converts property name into file name,
// e.g. secrets.username -> /secrets/username.txt
return Files.readAllLines(Paths.get("/"+name.replace('.','/')+".txt")).get(0);
}
return null;
}
}
public class SecretStorePropertySourceEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
environment.getPropertySources()
.addLast(new SecretStorePropertySource("customSecretPropertySource",
new SecretStorePropertySource()));
}
}
Add to src/main/resources/META-INF/spring.factories
file
org.springframework.boot.env.EnvironmentPostProcessor=com.mycompany.myproduct.SecretStorePropertySourceEnvironmentPostProcessor
secrets.
prefix to pass property through your sourcespring.datasource.username=${secrets.username}
spring.datasource.password=${secrets.password}
However, if you are going to provide it via file then just rename this file to application-secrets.yml
and place on target server into config
folder which itself is located in the same folder where application jar copied.
Now you can ask SpringBoot to load it by adding secrets
into active profiles list.
Not saying I'm advising it but you also can make your code working
@Configuration
public class Secrets {
@Bean("SecretUserName")
public String getUserName() {
try {
return Files.readAllLines(Paths.get("/secrets/username.txt")).get(0);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
@Bean("SecretUserPassword")
public String getPassword() {
try {
return Files.readAllLines(Paths.get("/secrets/password.txt")).get(0);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
}
and adding following lines to application.yml
spring.datasource.username=#{@SecretUserName}
spring.datasource.password=#{@SecretUserPassword}
Upvotes: 3