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
- Guice bundle registered (in application
initialize
method) - Perform classpath scan for commands (optional)
- Guice bundle registered (in application
- 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)
- Bind dropwizard objects: Environment, Configuration, Bootstrap
- Scan for installers (in auto configuration mode)
- Scan for extensions (in auto configuration mode)
- Register
GuiceFeature
in environment (jerseyFeature
which will trigger jersey side installations) - Apply lazy jersey bindings
- Activate guice servlet support, register GuiceFilter on admin and main contexts (could be disabled)
- 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- Register hk2-guice bridge (only guice to hk way to let hk managed beans inject guice beans)
- Run jersey specific installers (resource, extension)
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 (whenMultivaluedParameterExtractorProvider
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
.