Custom ConfigStores
The ConfigStore
API has been written to allow easy development of custom configuration storage classes.
The example below shows a starting point for an implementation based on polling a relational database.
The source can be found here: SqlStore.
Completing it is left as an exercise:
Example Store Class
public class SqlStore extends ConfigStore {
private final String jdbcUrl;
private final String tableName, nameColumn, valueColumn;
private final Timer watcher;
private final ConcurrentHashMap cache = new ConcurrentHashMap();
protected SqlStore(ConfigStore.Builder builder) {
super(builder);
this.jdbcUrl = builder.jdbcUrl;
this.tableName = builder.tableName;
this.nameColumn = builder.nameColumn;
this.valueColumn = builder.valueColumn;
int pollInterval = builder.pollInterval;
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
SqlStore.this.poll();
}
};
this.watcher = new Timer("MyTimer");
watcher.scheduleAtFixedRate(timerTask, 0, pollInterval * 1000);
}
synchronized void poll() {
// Loop through all our entries and find the latest values.
for (Map.Entry e : cache.entrySet()) {
String name = e.getKey();
String cacheContents = e.getValue();
String newContents = getDatabaseValue(name);
// Change detected!
if (! cacheContents.equals(newContents))
update(name, newContents);
}
}
// Reads the value from the database.
protected String getDatabaseValue(String name) {
// Implement me!
return null;
}
@Override /* ConfigStore */
public boolean exists(String name) {
// Implement me!
return false;
}
@Override /* ConfigStore */
public synchronized String read(String name) {
String contents = cache.get(name);
if (contents == null) {
contents = getDatabaseValue(name);
update(name, contents);
}
return contents;
}
@Override /* ConfigStore */
public synchronized String write(String name, String expectedContents, String newContents) {
// This is a no-op.
if (StringUtils.eq(expectedContents, newContents))
return null;
String currentContents = read(name);
if (expectedContents != null && StringUtils.ne(currentContents, expectedContents))
return currentContents;
update(name, newContents);
// Success!
return null;
}
@Override /* ConfigStore */
public synchronized SqlStore update(String name, String newContents) {
cache.put(name, newContents);
super.update(name, newContents); // Trigger any listeners.
return this;
}
@Override /* Closeable */
public synchronized void close() {
if (watcher != null)
watcher.cancel();
}
}