Currently, the config API is statically defined and not extensible. It needs to be extensible.
At the moment, the only SPI is the ability to inject Guice modules. Guice doesn't define any lifecycle. It simply creates an "application context" which you can retrieve beans from. We will likely need to implement our own lifecycle and make it fundamental to the way Ratpack bootstraps.
This is my proposed plan:
There are two distinct phases of bootstrapping; config then application. This creates a separation between config extension modules and application extension modules. Config types have no access to runtime types, but app types can depend on config types (in order to configure themselves).
We introduce RatpackAppBuilder
, which looks like this:
interface RatpackAppBuilder {
// Mutable list of modules defining config time beans
List<Module> getConfigModules()
// Callback called by Ratpack after initializing all config modules
// Allows access to mutate the config beans before the runtime is bootstrapped
void onConfig(Handler<Config>)
// Mutable list of modules defining runtime beans
List<Module> getRuntimeModules()
}
Config.groovy
looks something like this:
interface Config {
<T> T get(T configObjectType)
<T> T config(T configObjectType, Handler<T> configurer)
}
(you can infer the closure overrides for the Groovy module)
In the Groovy script mode, this type backs the config.groovy
script…
configModules << new MyConfigExtensionModule()
onConfig {
config(MyCustomConfigObject) {
someSetting = foo
}
}
runtimeModules << new MyRuntimeModuleThatDependsOnMyCustomConfigObject()
It does mean that there is no static list of config options, but there can't be if it is to be extensible.