Spring S3 Property Loader
S3 Property Loader has the aim of allowing loading of Spring property files from S3 bucket, in order to guarantee stateless machine configuration.
Spring PropertyConfigurer uses PropertiesFactoryBean
to load property files from AWS S3 bucket.
Install
Gradle:
repositories {
jcenter()
}
compile "com.spring.loader:s3-loader:3.0.0"
Maven:
<dependency>
<groupId>com.spring.loader</groupId>
<artifactId>s3-loader</artifactId>
<version>3.0.0</version>
<type>pom</type>
</dependency>
How to use
- Adding this annotation to any spring managed bean
@S3PropertiesLocation("my-bucket/my-folder/my-properties.yaml")
- Using a specific profile to only load properties if the app is running with that profile
@S3PropertiesLocation(value = "my-bucket/my-folder/my-properties.properties", profiles = "production")
- Load from a System env variable
@S3PropertiesLocation(value = "${AWS_S3_LOCATION}", profiles = "developer") // or @S3PropertiesLocation(value = "${AWS_S3_BUCKET}/application/my.properties", profiles = "developer")
Binding properties to a POJO
You can bind the externally loaded properties to a POJO as well.
For e.g., if you have a YAML file as
zuul:
routes:
query1:
path: /api/apps/test1/query/**
stripPrefix: false
url: "https://test.url.com/query1"
query2:
path: /api/apps/test2/query/**
stripPrefix: false
url: "https://test.url.com/query2"
index1:
path: /api/apps/*/index/**
stripPrefix: false
url: "https://test.url.com/index"
Then you can bind the properties to a POJO using ConfigurationProperties:
@Component
@ConfigurationProperties("zuul")
public class RouteConfig {
private Map<String, Map<String, String>> routes = new HashMap<>();
public void setRoutes(Map<String, Map<String, String>> routes) {
this.routes = routes;
}
public Map<String, Map<String, String>> getRoutes() {
return routes;
}
}
// or
@Component
@ConfigurationProperties("zuul")
public class RouteConfig {
private Map<String, Route> routes;
public void setRoutes(Map<String, Route> routes) {
this.routes = routes;
}
public Map<String, Route> getRoutes() {
return routes;
}
public static class Route {
private String path;
private boolean stripPrefix;
String url;
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public boolean isStripPrefix() {
return stripPrefix;
}
public void setStripPrefix(boolean stripPrefix) {
this.stripPrefix = stripPrefix;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
try {
return new ObjectMapper().writeValueAsString(this);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return this.toString();
}
}
@Override
public String toString() {
try {
return new ObjectMapper().writeValueAsString(this);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return this.toString();
}
}
Refreshing properties in runtime
You can force your application to load properties from S3 again without restart. S3 Properties Loader uses a Spring Cloud feature that allows the spring beans annotated with @RefreshScope
to reload properties.
To work, it is only necessary to inject the S3PropertiesContext
bean and call refresh()
method. After this, S3 Properties Loader will get properties again from s3 bucket defined previously and refresh your beans annotated with @RefreshScope
.
tip: You can create a endpoint that calls this class and refresh your application via endpoint or create a @Scheduled
class which updates from time to time.
Example:
@RestController
public SomeController {
@Autowired
private S3PropertiesContext s3PropertiesContext;
@PostMapping("/refresh-properties")
public void refresh() {
s3PropertiesContext.refresh();
}
}
Requisites
Official spring aws sdk lib.
Problems and Issues
Found some bug? Have some enhancement ? Open a Issue here