edit

Integration lifecycle

Jersey2 guice integration is more complicated than for jersey1, because of HK2 container, used by jersey2.

Note

Many people ask why not just use HK2 instead of guice as it's already provided. Unfortunately, it's hard to use it in the same elegant way as we can use guice. HK context is launched too late (after dropwizard run phase). For example, it is impossible to use HK to instantiate dropwizard managed object because managed must be registered before HK context starts.

Guice integration done in guice exclusive way as much as possible: everything should be managed by guice and invisibly integrated into HK2. Anyway, it is not always possible to hide integration details, especially if you need to register jersey extensions.

Guice context starts before HK context.

Lifecycle

  • Dropwizard configuration phase
  • Dropwizard run phase
    • Dropwizard runs bundles (guice bundle is one of them so guice initialization may be performed between other dropwizard bundles)
    • Search guicey bundles in dropwizard bundles (optional)
    • Lookup guicey bundles
    • Apply configuration from guicey bundles
    • Injector creation (using factory)
    • Injector created
      • Call installers to register extensions
    • Your application's run method executed. Injector is already available, so any guice bean could be accessed
  • Jersey start
    • Managed beans started
    • HK2 context creation
      • GuiceFeature (registered earlier) called

Note

Any EnvironmentCommand did no start jersey, so managed objects will not be started. Also, all jersey related extensions will not be started. Still, core guice context will be completely operable.

When guice context is created, jersey context doesn't exist and when jersey context is created it doesn't aware of guice existence.

Cross context bindings

Access jersey beans from guice

To access HK bindings we need HK2 ServiceLocator: it's instance is registered by GuiceFeature (in time of HK context startup).

Jersey components are bound as providers:

binder.bind(jerseyType).toProvider(new LazyJerseyProvider(jerseyType));

Internally this provider will perform lookup in HK service locator:

injector.getInstance(ServiceLocator.class).getService(jerseyType);

This way jersey beans are "bridged" to guice. They can't be accessed directly in guice beans at injector creation time (as there is nothing to "bridge" yet).

@Inject Provider<JerseyType> provider must be used to access such beans.

See more details in jersey bindings module.

Access guice beans from jersey

Note

It's almost never required to care about beans visibility from HK side because guicey already did all required bindings.

HK could see all guice beans because of registered guice-bridge. But it doesn't mean HK can analyze all guice beans to search for extensions (it can resolve only direct injection).

Specific jersey installers (resource, extension) create required bindings manually in time of HK context creation.

Jersey extensions installer handles most specific installation cases (where HK knowledge is required). It uses the same technic, as the other side binding:

binder.bindFactory(new LazyGuiceProvider(guiceType)).to(type)

On request, factory will simply delegate lookup to guice injector:

injector.getInstance(guiceType);

Tip

If you just want to add some beans in HK context, annotate such beans with @Provider and @HK2Managed - provider will be recognized by installer and hk managed annotation will trigger simple registration (overall it's the same as write binding manually).

@HK2Managed
@Provider
public class MyBeanMangedByHK { ... }    

For more details look jersey provider installer

Problematic cases

The problems may appear with binding of jersey extensions. Good example is ValueFactoryProvider. Most likely you will use AbstractValueFactoryProvider as base class, but it declares direct binding for MultivaluedParameterExtractorProvider. So such bean would be impossible to create eagerly in guice context.

There are two options to solve this:

  • use @LazyBinding: bean instance will not be created together with guice context (when MultivaluedParameterExtractorProvider is not available), and creation will be initiated by HK, when binding could be resolved.
  • or use @HK2Managed this will delegate instance management to HK, but still guice specific extensions may be used.

In other cases simply wrap jersey specific bindings into Provider.