Bindings¶
Guicey always installs GuiceBootstrapModule
which registers the following bindings:
- Dropwizard objects:
io.dropwizard.setup.Bootstrap
io.dropwizard.Configuration
io.dropwizard.setup.Environment
- Detailed configuration bindings (by root classes, interfaces, yaml path or unique subtype)
- Jersey objects (including request scoped)
- Guicey special objects
- All installed extensions
Tip
All registered bindings could be seen with guice report.
Configuration¶
Configuration
bound to guice as:
io.dropwizard.Configuration
- Your configuration class (
MyConfiguration extends Configuration
) - All classes between them
For example, if
MyConfiguration extends MyAbstractConfiguration extends Configuration
Then MyAbstractConfiguration
will be also bound and the following injection will work:
@Inject MyAbstractConfiguration conf
Note
Configuration object bindings could be declared with or without qualifier @Config
.
So @Inject @Config MyAbstractConfiguration conf
will also work. It is suggested to always
use qualifier (to get in common with direct value bindings), but it's up to you.
If root configuration classes implement interfaces then configuration could be bound by interface.
This may be used to support common Has<Something>
configuration interfaces convention used to recognize your extension configuration in configuration object.
public interface HasFeatureX {
FeatureXConfig getFetureXConfig();
}
public class MyConfiguration extends Configuration implements HasFeatureXConfig {...}
public class MyBean {
@Inject @Config HasFeatureX conf;
...
}
Interface binding will ignore interfaces in java.*
or groovy.*
packages (to avoid unnecessary bindings).
Tip
Consider using direct sub configuration object binding instead of marker interface if object uniqueness is guaranteed in user configuration.
Yaml config introspection¶
Guicey performs Configuration
object introspection to provide access for
configured yaml values by path or through sub-objects.
Warning
Additional configuration objects are not bound when yaml introspection is disabled
Raw introspection result could be injected directly (for reporting or analysis):
@Inject ConfigurationTree tree;
Tip
All available configuration bindings could be seen with .printConfigurationBindings()
report
(use .printAllConfigurationBindings()
to see also core dropwizard configuration values).
This report is executed before injector creation so use it in cases when injector fail to inject configration value to validate binsinds correctness.
Unique objects¶
Unique sub-object (sub configuration classes appeared once) could be injected directly.
For example, the following config contains two (custom) unique sub objects:
public class MyConfig extends Configuration {
@JsonProperty AuthConfig auth;
@JsonProperty DbConfig db;
}
Which could be injected directly:
@Inject @Config AuthConfig auth;
@Inject @Config DbConfig db;
Tip
This is very useful for re-usable modules, which are not aware of your configuration object structure, but require only one sub configuration object:
public class MyConfig extends Configuration {
@JsonProperty FeatureXConfig featureX;
}
Somewhere in module service:
public class FeatureXService {
@Inject @Config FeatureXConfig featureX;
}
Value by path¶
All visible configuration paths values can be directly bound:
public class MyConfig extends Configuration {
SubConf sub;
}
public class SubConf {
String smth;
List<String> values;
}
@Inject @Config("sub") SubConf sub;
@Inject @Config("sub.smth") String smth;
@Inject @Config("sub.values") List<String> values;
Note
Path bindings are available even for null values. For example, if sub configuration object
is null, all it's sub paths will still be available (by class declarations).
The only exception is conditional mapping like dropwizard server
when available paths
could change, depending on configuration (what configuration type will be used)
Note
Generified types are bound only with generics (with all available type information).
If you have SubConf<T> sub
in config, then it will be bound with correct generic SubConfig<String>
(suppose generic T is declared as String).
Value type, declared in configuration class is used for binding, but there are two exceptions.
First, if declared type is declared as collection (Set
, List
, Map
) implementation then binding will use
base collection interface:
ArrayList<String> value
@Inject @Config("value") List<String> vlaue;
Second, if, for some (unforgivable) reason, property is declared as Object
in configuration,
then binding type will depend on value presence:
@Config("path") Object val
- when value is null@Config("path") ValueType val
- actual value type, when value is not null
It is assumed that in such case value would be always present (some sort of property-selected binding, like dropwizard server
).
Tip
If provided value bindings are not enough for your case, you can declare your own value bindings:
Get introspcetion result object (ConfigurationTree
) in guice module and bind values
the way you need it:
public class MyConfigBindingsModule extends DropwizardAwareModule {
@Override
public void configure() {
bind(String.class).annotatedWith(Names.named("db.url"), configuration("db.url));
}
}
Environment binding¶
Dropwizard io.dropwizard.setup.Environment
is bound to guice context.
It is mostly useful to perform additional configurations in guice bean for features not covered with installers. For example:
public class MyBean {
@Inject
public MyBean(Environment environment) {
environment.lifecycle().addServerLifecycleListener(new ServerLifecycleListener {
public void serverStarted(Server server) {
callSomeMethod();
}
})
}
}
It's not the best example, but it illustrates usage (and such things usually helps to quick-test something).
See also authentication configuration example.
Jersey specific bindings¶
Jersey bindings are not immediately available, because HK2 context starts after guice,
so use Provider
to inject these bindings.
These bindings available after HK2 context start:
jakarta.ws.rs.core.Application
jakarta.ws.rs.ext.Providers
org.glassfish.hk2.api.ServiceLocator
org.glassfish.jersey.server.internal.inject.MultivaluedParameterExtractorProvider
Request-scoped bindings:
jakarta.ws.rs.core.UriInfo
jakarta.ws.rs.container.ResourceInfo
jakarta.ws.rs.core.HttpHeaders
jakarta.ws.rs.core.SecurityContext
jakarta.ws.rs.core.Request
org.glassfish.jersey.server.ContainerRequest
org.glassfish.jersey.server.AsyncContext
Tip
Read about jersey bindings implementation in lifecycle section.
Request and response¶
By default, GuiceFilter
is enabled on both contexts (admin and main). So you can inject
request and response objects and use under filter, servlet or resources calls (guice filter wraps all web interactions).
If you disable guice filter with .noGuiceFilter() then guicey will bridge objects from HK2 context:
jakarta.servlet.http.HttpServletRequest
jakarta.servlet.http.HttpServletResponse
This means you can still inject them, but request and response will only be available under resource calls (the only part managed by jersey).
Example usage:
@Inject Provider<HttpServletRequest> requestProvider;
Note
Pay attention, that in guice-managed resources @Context
field bindings
must be replaced with providers.
Options¶
ru.vyarus.dropwizard.guice.module.context.option.Options
binding provides access to guicey options:
@Inject Options options;
Example usage:
Preconditions.checkState(options.get(GuiceyOptions.UseHkBridge),
"HK2 guice bridge is required!")
Guicey configuration¶
ru.vyarus.dropwizard.guice.module.GuiceyConfigurationInfo
binding provides access
to guicey configuration details:
@Inject GuiceyConfigurationInfo info
Extension bindings¶
Summary
Normally, you don't need to know about extension bindings because they are mostly useless for application, but this section is important in case of problems.
In order to support guice binder().requireExplicitBindings()
option guicey binds
all extensions with untargeted binding: binder().bind(YourExtension.class)
.
But there are three exceptions:
- Installers with custom binding logic (like a plugins installer)
- If extension was detected from binding (obviously binding already exists)
- If extension is annotated with
@LazyBinding
As injector is created in Stage.PRODUCTION
, all singleton extensions will be instantiated
in time of injector startup (injector stage could be changed in main bundle).