Re: Hierarchical Injectors

73 views
Skip to first unread message

Sam Berlin

unread,
Jul 23, 2008, 12:26:02 PM7/23/08
to google...@googlegroups.com
(FWIW, I am using the latest snapshot tag.)

On Wed, Jul 23, 2008 at 12:25 PM, Sam Berlin <sbe...@gmail.com> wrote:
> Hi Folks,
>
> I'm attempting to use the hierarchical injectors, but it doesn't seem
> to be working like I thought it would. Is the following use-case
> supported? ...
>
> ---
>
> Injector parent = Guice.createInjector(new AbstractModule() {
> public void configure() {
> bind(Foo.class).to(FooImpl.class);
> }
> });
>
> Injector child = Guice.createInjector(parent, new AbstractModule() {
> public void configure() {
> bind(Bar.class).to(BarImpl.class);
> }
> });
>
> interface Foo {}
> class FooImpl implements Foo {}
>
> interface Bar {}
> class BarImpl implements Bar {
> @Inject Foo foo;
> }
>
> -----
>
> In a nutshell -- can the child have injections that are bound from the
> parent? I had thought this was a purpose, but in my attempts, I keep
> getting an error:
>
> com.google.inject.CreationException: Guice configuration errors:
>
> 1) Error at org.limewire.inject.AbstractModuleTest$BarImpl.foo(AbstractModuleTest.java:61):
> No implementation for org.limewire.inject.AbstractModuleTest$Foo was bound.
>
> 1 error[s]
> at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:324)
> at com.google.inject.InjectorBuilder.validate(InjectorBuilder.java:168)
> at com.google.inject.InjectorBuilder.build(InjectorBuilder.java:99)
> at com.google.inject.Guice.createInjector(Guice.java:139)
> at com.google.inject.Guice.createInjector(Guice.java:126)
> [...]
>
> Thanks much,
> Sam
>

Sam Berlin

unread,
Jul 23, 2008, 12:54:47 PM7/23/08
to google...@googlegroups.com
Also, it seems like if I add
.in(Scopes.SINGLETON);
to the Foo binding, the error goes away.

My actual error cropped up because the parent injector was binding
using AssistedInject, so it was binding a provider. When I added
in(Scopes.SINGLETON) to the provider binding, the hierarchical error
disappeared. That seems a little counter-intuitive, as it shouldn't
matter whether or not the provider is a singleton.

Is there some technical limitation to hierarchical injectors that
requires the bindings to needed bindings to be singletons? It would
be better, IMO, if the child injectors worked simply as an extension
to the parent injector.

My use case is that I'm investigating the feasibility of using Guice
for our UI, in addition to the core. The core needs to be constructed
early on, initialized, and checked for consistency. The UI needs to
be constructed in the Swing thread (otherwise Swing breaks -- it needs
all classes constructed in its thread). This would seem to be a prime
candidate for hierarchical injectors -- build the core, then build the
UI which requires the core.

Sam

limpb...@gmail.com

unread,
Jul 23, 2008, 4:15:22 PM7/23/08
to google-guice
On Jul 23, 9:54 am, "Sam Berlin" <sber...@gmail.com> wrote:
> Is there some technical limitation to hierarchical injectors that
> requires the bindings to needed bindings to be singletons?

The current implementation of hierarchical
injectors isn't what will be in v. 2.0 and we're
going to rewrite it.

If you've got some use cases for hierarchical
injectors, please please post 'em on the bug
so we can take them into consideration when
writing the new implementation.

Brian

unread,
Jul 25, 2008, 12:17:02 AM7/25/08
to google-guice
I'm considering hierarchical injectors for test cases. I'd like to
just overwrite bindings in production injectors with my test bindings,
rather than rebuild the entire test injector with mostly duplicated
code. I believe I'm running into the same issue as Sam. I am using
the same method and my parent bindings seem unavailable from my child
injector.

That's my use case for chaining injectors, if that helps.

Simone Tripodi

unread,
Aug 3, 2008, 3:32:28 PM8/3/08
to google-guice
Hi All,
I would like to know if is there a sort of work-around in 1.0 Release
to build Injectors in a Hierarchical way, starting from an existing
Injector.
Thank you in advance!!!
Simone

med...@gmail.com

unread,
Aug 5, 2008, 12:10:28 AM8/5/08
to google-guice
Sure, loop over the exiting injector's bindings ( getBindings() )
inside a module, rebinding them using toProvider(...) as you go. You
can respect the parent injector's bindings' scopes, and also treat
constant bindings special, using bindConstant.

Simone Tripodi

unread,
Aug 5, 2008, 3:48:24 AM8/5/08
to google-guice
Hi Medotin,
I've just implemented what you suggested and *it rocks*!!!
Thank you very much!
Just a small question: I didn't understand if singletons will be re-
instanced in the child Injector - can you explain me please?
Thank you again,

Simone

med...@gmail.com

unread,
Aug 6, 2008, 11:17:01 PM8/6/08
to google-guice
They will not be reinstantiated because the provider you pass
to .toProvider is the exact one being used up above. I got this idea
from Jesse.

Simone Tripodi

unread,
Aug 7, 2008, 2:30:39 AM8/7/08
to google-guice
Hi Medotin,
thank you very much for your reply, you're absolutely right!!!!
I debugged a bit the application and I watched with my own eyes
the singletons won't be re-instantiated!!! Thank you again!
Simone

Sam Berlin

unread,
Aug 13, 2008, 11:27:38 AM8/13/08
to google...@googlegroups.com
Do you explicitly ignore bindings to Logger, Injector & Stage?

Sam

Simone Tripodi

unread,
Aug 13, 2008, 2:29:36 PM8/13/08
to google-guice
Hi Sam,
yes, I ignore bindings of all 3 objects you mentioned.
I wrote a simple InjectorFactory like this:

final class InjectorFactory {

private InjectorFactory() {
}

@SuppressWarnings("unchecked")
public static Injector createInjector(final Injector parent,
final List<Module> modules) {
modules.add(new Module() {
public void configure(Binder binder) {
for (Entry<Key<?>, Binding<?>> bindingEntry :
parent.getBindings().entrySet()) {
Key<?> key = bindingEntry.getKey();
Type keyType = key.getTypeLiteral().getType();
Provider provider =
bindingEntry.getValue().getProvider();

if (!keyType.equals(Injector.class)
&& !keyType.equals(Logger.class)
&& !keyType.equals(Stage.class)) {
binder.bind(key).toProvider(provider);
}
}
}
});
Injector injector = Guice.createInjector(modules);
return injector;
}

}

Simple, but it works.
Cheers,
Simone

On 13 Ago, 17:27, "Sam Berlin" <sber...@gmail.com> wrote:
> Do you explicitly ignore bindings to Logger, Injector & Stage?
>
> Sam
>

Marko Kocić

unread,
Aug 14, 2008, 5:02:25 AM8/14/08
to google-guice
Nice, now you only have to take care that child modules can override
some of the parent bindings, and we have a nice contrib package to
Guice.

Maybe creating temporary child injector first, use it go get bindings
from all modules, then adding bindings from temp injector and parent
injector that are not already in temp injector in new child injector
that will be returned?

Simone Tripodi

unread,
Aug 14, 2008, 9:42:29 AM8/14/08
to google-guice
Hi Marko,
as far as I know, the hierarchical injector has already been planned
for next Guice's release and, if you check the trunk code (I mean the
Injector class

http://code.google.com/p/google-guice/source/browse/trunk/src/com/google/inject/Guice.java

), you can see the Google team's approach.
Hope it helps!
Cheers,
Simone

Marko Kocić

unread,
Aug 14, 2008, 4:14:01 PM8/14/08
to google-guice
On 14 авг, 15:42, Simone Tripodi <simone.trip...@gmail.com> wrote:
> Hi Marko,
> as far as I know, the hierarchical injector has already been planned
> for next Guice's release and, if you check the trunk code (I mean the
> Injector class
>
> http://code.google.com/p/google-guice/source/browse/trunk/src/com/goo...
>
> ), you can see the Google team's approach.
> Hope it helps!

Looks nice, but I'll try it inside my project as soon as I can.
Does it allow to override some bindings from parent?
I already have code that does this, but don't like how it looks ;)

> Cheers,
> Simone

Regards,
Marko

Simone Tripodi

unread,
Aug 15, 2008, 6:06:01 AM8/15/08
to google-guice
Hi Marko,
the small code I posted doesn't allow override parent's binding, if
you try doing it an Exception will thrown.
I've never had the need of overring modules, but I suggest you taking
a look on

http://code.google.com/p/google-guice/source/browse/trunk/src/com/google/inject/Guice.java

where a method to override modules is declared

public static Module overrideModule(Module module, Module
overridesModule) {
return Modules.override(module).with(overridesModule);
}

and so the Modules class

http://code.google.com/p/google-guice/source/browse/trunk/src/com/google/inject/util/Modules.java

I hope it helps you on your issue!
Yours,
Simone

Marko Kocić

unread,
Aug 15, 2008, 8:29:39 AM8/15/08
to google-guice


On 15 авг, 12:06, Simone Tripodi <simone.trip...@gmail.com> wrote:
> Hi Marko,
> the small code I posted doesn't allow override parent's binding, if
> you try doing it an Exception will thrown.

I already have the code where I explicitly pass list of Bindings that
are overriden,
and when creating child injector I only add those Bindings from the
parent that are
not on that list.
That approach works, but it is ugly since I had to provide list of
ignored bindings.
What I would like to see is a way to override existing Injector where
explicit bindings
from modules will automatically override bindings from parent, without
that manual step.

> I've never had the need of overring modules, but I suggest you taking
> a look on
>
> http://code.google.com/p/google-guice/source/browse/trunk/src/com/goo...
>
> where a method to override modules is declared
>
> public static Module overrideModule(Module module, Module
> overridesModule) {
>     return Modules.override(module).with(overridesModule);
>   }
>
> and so the Modules class
>
> http://code.google.com/p/google-guice/source/browse/trunk/src/com/goo...
>
> I hope it helps you on your issue!

This overrding only works for creating new Injectors with a list of
modules,
but is not usable if you want to override bindnings of already created
Injector.

> Yours,
> Simone

Regards,
Marko
Reply all
Reply to author
Forward
0 new messages