How to bind a catch-all provider?

215 views
Skip to first unread message

Gili

unread,
Oct 27, 2013, 11:19:15 AM10/27/13
to google...@googlegroups.com
I am trying to integrate two DI systems: Guice and HK2. I'd like to implement the following behavior:

1. When Injector.getInstance() is invoked, iterate through all bindings (as it normally does).
2. If no match is found, ask HK2 to inject the type.
3. If no match is found, throw an error.

I'm not sure how to implement step #2. Because we lack this behavior, we're stuck with an ugly @HK2Inject as seen here: https://hk2.java.net/guice-bridge/index.html

Any ideas?

Gili

Sam Berlin

unread,
Oct 27, 2013, 11:24:08 AM10/27/13
to google...@googlegroups.com
There's no built-in way to do this.  Depending on the scope, it's maybe possible to use TypeListeners and custom injections to do this.  

 sam


--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-guice...@googlegroups.com.
To post to this group, send email to google...@googlegroups.com.
Visit this group at http://groups.google.com/group/google-guice.
For more options, visit https://groups.google.com/groups/opt_out.

cowwoc

unread,
Oct 27, 2013, 11:45:47 AM10/27/13
to google...@googlegroups.com
Hi Sam,

    Out of curiosity, is it possible to make this work using @Inject instead of @InjectLogger? As in:

@Inject Logger logger;

    The goal is to intercept @Inject for an unknown type, and ask HK2 to try injection. Using custom annotations kind of defeat the purpose (we already have @HK2Inject which we're trying to get away from).

Gili
You received this message because you are subscribed to a topic in the Google Groups "google-guice" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-guice/YXJuAdw5G24/unsubscribe.
To unsubscribe from this group and all its topics, send an email to google-guice...@googlegroups.com.

Sam Berlin

unread,
Oct 27, 2013, 11:53:37 AM10/27/13
to google...@googlegroups.com
Issue 49 provides a good history of this request -- currently closed as "Won't Fix".

 sam

cowwoc

unread,
Oct 27, 2013, 11:59:26 AM10/27/13
to google...@googlegroups.com

    What happens if I take https://code.google.com/p/google-guice/wiki/CustomInjections and change:

field.isAnnotationPresent(InjectLogger.class)

    to

field.isAnnotationPresent(Inject.class)

    Wouldn't that work as I expect?

Gili

Sam Berlin

unread,
Oct 27, 2013, 12:11:34 PM10/27/13
to google...@googlegroups.com
No idea to be honest, I haven't played around much with TypeListener & friends.  Give it a shot and let us know how it goes.

 sam

Stuart McCulloch

unread,
Oct 27, 2013, 1:14:38 PM10/27/13
to google...@googlegroups.com
On 27 Oct 2013, at 15:59, cowwoc wrote:

    What happens if I take https://code.google.com/p/google-guice/wiki/CustomInjections and change:

field.isAnnotationPresent(InjectLogger.class)

    to

field.isAnnotationPresent(Inject.class)

    Wouldn't that work as I expect?

I don't believe so, because Guice will report the missing binding as an error before it gets round to starting custom injection. 

The only way I've found to provide a kind of "auto-binding" without modifying Guice internals is to use the SPI to scan for missing dependencies and then add bindings for them.

For example:

Guice.createInjector( new WireModule( appModuleA, appModuleB, serviceModuleC ) );

where WireModule uses Elements.elements(...) to process, analyze, and reapply the various elements - keeping track of what dependencies are used and what keys are bound.

The downside of this approach is that you need to remember wrap the WireModule around your application modules, as well as the up-front cost of analyzing the elements. It also doesn't work so well with just-in-time bindings (such as asking the injector for an instance of FooImpl.class, where FooImpl is not referenced at all in the bindings provided to the injector and therefore was not available for analysis). 

The benefit of doing the analysis upfront is that the final binding elements are static and can be analyzed by tooling just like those from any other module.

cowwoc

unread,
Oct 27, 2013, 10:40:02 PM10/27/13
to google...@googlegroups.com
Hi Sam and Stuart,

    I got up to this point:

    @Inject
    public DepartmentsResource(Injector injector, UriInfo uriInfo)

    When I try injecting the above constructor, Guice recognizes @javax.inject.Inject and com.google.Injector but doesn't recognize UriInfo. The problem is that UriInfo is not defined in any Guice module, nor can it be, because only Jersey knows how to inject this type and Jersey only speaks to HK2. TypeListener.hear() is never invoked for UriInfo so I have no way of providing Guice with the instance to be injected.

    I am having a very hard time here. What's even more frustrating is that Spring has a working HK2 bridge so there is less pressure on HK2/Jersey to make this work. Any ideas?

Gili

Stuart McCulloch

unread,
Oct 28, 2013, 7:09:53 AM10/28/13
to google...@googlegroups.com
On 28 Oct 2013, at 02:40, cowwoc wrote:

Hi Sam and Stuart,

    I got up to this point:

    @Inject
    public DepartmentsResource(Injector injector, UriInfo uriInfo)

    When I try injecting the above constructor, Guice recognizes @javax.inject.Inject and com.google.Injector but doesn't recognize UriInfo. The problem is that UriInfo is not defined in any Guice module, nor can it be, because only Jersey knows how to inject this type and Jersey only speaks to HK2. TypeListener.hear() is never invoked for UriInfo so I have no way of providing Guice with the instance to be injected.

    I am having a very hard time here. What's even more frustrating is that Spring has a working HK2 bridge so there is less pressure on HK2/Jersey to make this work. Any ideas?

If you want to avoid any change to Guice internals then the analyze+bind approach I outlined below is the only generic solution I've found.

When you find missing dependency keys using the SPI at binding time then you can bind them to a generic service locator such as via HK2 which will then be called at injection time.

The other approach we've used in the past (which is specific to Jersey integration) is to use scoped @Provides to delegate requests for UriInfo via Jersey:


Otherwise unfortunately there's no quick fix I can point you to.

If people are interested I can resurrect my BindingFactory patch to provide a starting point for discussion (but based on the feedback in issue 49 I'm not sure that's a viable option).
Reply all
Reply to author
Forward
0 new messages