The generated classes will be saved to
target/generated-sources/vespa-configgen-plugin, when the
generate-sources phase of the build is executed.
The def-file motd.def
is used in this tutorial, and a class called MotdConfig
was generated (in the package myproject).
It is a subtype of ConfigInstance.
When using only the config system (and not other parts of Vespa or
the JDisc container), pull in that by using this in pom.xml:
To retrieve the config in the application, create a ConfigSubscriber.
A ConfigSubscriber is capable of subscribing to one or more configs.
The example shown here uses simplified error handling:
Note that isChanged() always will be true after the first call to nextConfig(),
it is included here to illustrate the API.
In many cases one will do this from a thread which loops the
nextConfig() call, and reconfigures your application if
isChanged() is true.
The second parameter to subscribe(), "motdserver2/0",
is the config id.
If one ConfigSubscriber subscribes to multiple configs,
nextConfig() will only return true if the configs are of
the same generation, i.e. they are "in sync".
ConfigSubscriber subscriber = new ConfigSubscriber();
ConfigHandle<MotdConfig> motdHandle = subscriber.subscribe(MotdConfig.class, "motdserver2/0");
ConfigHandle<AnotherConfig> anotherHandle = subscriber.subscribe(AnotherConfig.class, "motdserver2/0");
if (!subscriber.nextConfig()) throw new RuntimeException("Config timed out.");
// We now have a synchronized new generation for these two configs.
if (motdHandle.isChanged()) {
String message = motdHandle.getConfig().message();
int port = motdHandle.getConfig().port();
}
if (anotherHandle.isChanged()) {
String myfield = anotherHandle.getConfig().getMyField();
}
Simplified subscription
In cases like the first example above, where you only subscribe to one config, you may also subscribe using the
ConfigSubscriber.SingleSubscriber interface. In this case, you define a configure()
method from the interface, and call a special subscribe(). The method will start a dedicated config
fetcher thread for you. The method will throw an exception in the user thread if initial configuration fails,
and print a warning in the config thread if it fails afterwards. Example:
public class MyConfigSubscriber implements ConfigSubscriber.SingleSubscriber<MotdConfig> {
public MyConfigSubscriber(String configId) {
new ConfigSubscriber().subscribe(this, MotdConfig.class, configId);
}
@Override
public void configure(MotdConfig config) {
// configuration logic here
}
}
The disadvantage to using this is that one cannot implement custom error handling
or otherwise track config changes. If needed, use the generic method above.
Unit testing config
When instantiating a ConfigSubscriber,
one can give it a ConfigSource.
One such source is a ConfigSet. It consists of a set of Builders.
This is an example of instantiating a subscriber using this -
it uses 2 types of config, that were generated from files
app.def and string.def:
ConfigSet myConfigs = new ConfigSet();
AppConfig.Builder a0builder = new AppConfig.Builder().message("A message, 0").times(88);
AppConfig.Builder a1builder = new AppConfig.Builder().message("A message, 1").times(89);
myConfigs.add("app/0", a0builder);
myConfigs.add("app/1", a1builder);
myConfigs.add("bar", new StringConfig.Builder().stringVal("StringVal"));
ConfigSubscriber subscriber = new ConfigSubscriber(myConfigs);
To help with unit testing, each config type has a corresponding builder type.
The Builder is mutable whereas the ConfigInstance is not.
Use this to set up config fixtures for unit tests.
The ConfigSubscriber has a reload() method
which is used in tests to force the subscriptions into a new
generation. It emulates a vespa activate operation after
you have updated the ConfigSet.