Hi,
I've added in support for dynamic configuration and property re-injection. Below is some background and an explanation of how it works. As always, comments and feedback are greatly appreciated.
There have been a number of requests to provide a mechanism where application configuration and component properties can be changed at runtime. There were also requests to support specifying environment variables for property values so that they can be modified at startup. For example, there is often the need to supply the URLs of endpoints at startup when using a client library such as JAX-RS.
I have implemented an approach that extends the current property support to cover both sets of use cases. Using @Source and the ${..} syntax, it is now possible to specify an external property source as:
public class TestComponent {
@Property
@Source("${foo}")
protected String foo;
}
In the above example, the runtime will attempt to resolve the property using the 'foo' key first by checking any external configuration providers and as a fallback environment and VM properties respectively. There can be multiple external configuration providers installed and currently we have support for etcd. In the above case, Fabric3 will look for the property key in etcd under v2/keys/[domain]/configuration/foo (where [domain] is the runtime domain).
There are a couple of things to note:
1. Properties can be reinjected if they change (this is supported for etcd but not environment properties). For example, you can update or delete the entry in etcd at the change will be propagated to all F3 runtimes. This makes it easy to use tools like curl to update a cluster of runtimes:
2. Dynamic configuration can be a String or complex JSON type. For example, you can specify:
public class TestComponent {
@Property
@Source("${bar}")
protected Bar bar;
}
public class Bar {
private String bar;
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
}
and store the 'Bar' value as JSON in etcd:
It's also possible to add custom resolvers by creating a Fabric3 extension and implementing ConfigurationAgent:
public interface ConfigurationAgent {
String getValue(String key);
void registerListener(String key, Consumer<String> listener);
void unregisterListener(String key, Consumer<String> listener);
}
JSON deserialization and reinjection will be handled automatically by the runtime. This makes it possible to easily add additional configuration sources such as a distributed cache. You can even use this method to dynamically update a list of endpoint URLs.
Let me know if there are any questions, problems, or suggestions for improving this.
Jim