Module autowiring¶
Because guice modules are registered in dropwizard init section only Bootstrap
instance is available.
Often Environment
and Configuration
objects are also required.
Autowiring interfaces¶
Guicey can automatically inject environment objects into your module if it implements any of (or all of them):
BootstrapAwareModule
- access bootstrap instanceEnvironmentAwareModule
- access environment instanceConfigurationAwareModule
- access configuration instanceConfigurationTreeAwareModule
- access to configuration values by pathOptionsAwareModule
- access guicey options
Reference object will be set to module just before injector creation, so you can use it inside your
module logic (configuration
method).
Warning
Module autowiring will only work for modules directly set to modules()
(of main bundle or any guicey bundle).
public class MyModule implements EnvironmentAwareModule { private Environemnt environment; @Override public void setEnvironment(Environment environment) { this.environment = environment; } @Override protected void configure() { // use environment here } }
Autowiring base class¶
To avoid manually implementing interfaces (avoid boilerplate) you can use DropwizardAwareModule
as
base class which already implements all autowiring interfaces:
public class MyModule extends DropwizardAwareModule<MyConfiguration> { @Override protected void configure() { bootstrap() // Bootstrap instance environment() // Environment instance configuration() // MyConfiguration instance appPackage() // application class package configuratonTree() // configuration as tree of values confuguration(Class) // unique sub configuration configuration(String) // configuration value by yaml path configurations(Class) // sub configuration objects by type (including subtypes) options() // access guicey options sharedState(Class) // shared sctate access } }
Options¶
Options could be used in guice module to access guicey configurations:
public class MyModule extends DropwizardAwareModule<MyConfiguration> { @Override protected void configure() { // empty when guicey servlet support is dasabled if (options.<EnumSet>get(GuiceyOptions.GuiceFilterRegistration).isEmtpy()) { // do nothing } else { // register servlet module } } }
Or it could be some custom options usage.
Tip
If you are going to register module inside guicey bundle, you can simply resolve option value inside guicey bundle and pass it to module directly.
Configuration access¶
Tip
If you are going to register module inside guicey bundle, you can simply resolve configuration object inside guicey bundle and pass it to module directly (bundle has absolutely the same configuration access methods)
Unique feature config¶
When working with re-usable modules, it could be handy to rely on unique configuration object:
public class XFeatureModule extends DropwizardAwareModule<Configuration> { @Override protected void configure() { XFeatureConfig conf = configuration(XFeatureConfig.class); ... } }
Note that this module doesn't known exact type of user configuration, it just assumes that XFeatureConfig is declared somewhere in configuration (on any level) just once. For example:
public class MyConfig extends Configuration { @JsonProperty private XFeatureConfig xfeature; ... }
Important
Object uniqueness checked by exact type match, so if configuration also
contains some extending class (XFeatureConfigExt
) it will be different unique config.
Access by path¶
When you are not sure that configuration is unique, you can rely on exact path definition:
public class XFeatureModule extends DropwizardAwareModule<Configuration> { private String path; public XFeatureModule(String path) { this.path = path; } @Override protected void configure() { XFeatureConfig conf = configuration(path); ... } }
Path is declared by module user, who knows required configuration location:
GuiceBundle.builder() .modules(new XFeatureModule("sub.feature")) ... .build()
Where
public class MyConfig extends Configuration { @JsonProperty private SubConfig sub = { // pseudo code to combine class declarations @JsonProperty private XFeatureConfig feature; } ... }
Multiple configs¶
In case, when multiple config objects could be declared in user configuration, you can access all of them:
public class XFeatureModule extends DropwizardAwareModule<Configuration> { @Override protected void configure() { List<XFeatureConfig> confs = configurations(XFeatureConfig.class); ... } }
For configuration
public class MyConfig extends Configuration { @JsonProperty private XFeatureConfig xfeature; @JsonProperty private XFeatureConfig xfeature2; ... }
It wil return both objects: [xfeature, xfeature2]
Important
In contrast to unique configurations, this method returns all subclasses too.
So if there are XFeatureConfigExt
declared somewhere it will also be returned.
Custom configuration analysis¶
In all other cases (with more complex requirements) you can use ConfigurationTree
object which
represents introspected configuration paths.
public class XFeatureModule extends DropwizardAwareModule<Configuration> { @Override protected void configure() { // get all properties of custom configuration (ignoring properties from base classes) List<ConfigPath> paths = configurationTree().findAllRootPathsFrom(MyConfig.class); List markedTypes = paths.stream() .filter(it -> it.getValue() != null && it.getType().getValueType().hasAnnotation(MyMarker.class)) .map(it -> it.getValue()) .collect(Collectors.toList()); ... } }
In this example, module search for properties declared directly in MyConfig configuration
class with not null value and annotated (classes annotated, not properties!) with custom marker (@MyMarker
).
See introspected configuration structure description
Shared state¶
Special shortcuts provided to simplify access to shared state (if required).
public class XFeatureModule extends DropwizardAwareModule<Configuration> { @Override protected void configure() { SharedConfigObject config = sharedStateOrFail(SomeBundle.class, "Bundle %s is not registered", SomeBundle.class.getSimpleName()); } }
Shared state supposed to be declared in bundles and if required state is not available in time of injector creation then required bundle was not registered for sure.
Be careful with shared state as it is intended to be used only in rare cases when really complex integrations required.