Skip to content

Bindings

Guicey always installs GuiceBootstrapModule which registers the following bindings:

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).