Re: Injecting into classes that are constructed by framework code

60 views
Skip to first unread message

Cédric Beust ♔

unread,
Nov 12, 2012, 6:12:14 PM11/12/12
to google...@googlegroups.com
You should avoid referencing the injector directly like this since it defeats the purpose of injection (might be okay or not depending of how testable you want that class to be).

Have you considered assisted injection? Create these MyHandler objects with a factory that will be implemented by Guice. More details here:



-- 
Cédric




On Mon, Nov 12, 2012 at 1:55 PM, Alper Akture <alper....@gmail.com> wrote:
I'm using a game server that instantiates objects (Event handlers, etc) that I would like to inject references into. Since they construct these instances, is there an approach other than doing something in a default constructor like this to inject those dependencies? 

public class MyHandler {
  MyInectedClass myInjectedObj;
  public MyHandler() {
    myInjectedObj = MyInjector.getInstance().getInjector(MyInjectedClass.class);
  }
...
}

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-guice/-/jHP4Df5PrHYJ.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.

Thomas Broyer

unread,
Nov 12, 2012, 6:33:17 PM11/12/12
to google...@googlegroups.com


On Monday, November 12, 2012 10:55:32 PM UTC+1, Alper Akture wrote:
I'm using a game server that instantiates objects (Event handlers, etc) that I would like to inject references into. Since they construct these instances, is there an approach other than doing something in a default constructor like this to inject those dependencies? 

public class MyHandler {
  MyInectedClass myInjectedObj;
  public MyHandler() {
    myInjectedObj = MyInjector.getInstance().getInjector(MyInjectedClass.class);
  }
...
}

In cases where I cannot have my classes instantiated by Guice (in my case, more specifically GIN, but the patterns apply to Guice too), I use requestStaticInjection in my module to inject a static Provider<MyInjectedClass> inside the MyHandler class, then in the MyHandler constructor I .get() the provider to initialize the instance fields:

public class MyHandler {
    @Inject private static Provider<MyInjectedClass> myInjectedProvider;

    private final MyInjectedClass myInjectedObj;

    public MyHandler() {
        myInjectedObj = myInjectedProvider.get();
    }
}

Not much "cleaner" (if any), but thought I'd share anyway; it frees you from exposing the Injector, so you can keep it private to your entry-point (main(), ServletContextListener or whatever)

Cédric Beust ♔

unread,
Nov 12, 2012, 10:38:06 PM11/12/12
to Alper Akture, google...@googlegroups.com
Two more thoughts:
  • It's possible to inject the injector (I had to do this in at least one place in our code base). Not as bad as referencing a static injector, but still not optimal. I think we should create the annotation @Inception for this kind of trick.

  • In case you missed Christian's message a few days ago, consider defining the factory interface in the same class that it instantiates, in the spirit of "keeping things together". This alleviates the hassle of having to update both your class and your factory signatures when you add @Assisted parameters.
-- 
Cédric


-- 
Cédric




On Mon, Nov 12, 2012 at 6:14 PM, Alper Akture <alper....@gmail.com> wrote:
Thanks Cedric, I totally agree, I don't like using the injector directly. I wasn't aware of assisted injection, could be very useful. However, for many of my classes I have problems with, I give the framework the class name (in an init method that they call), and they do the instantiation. Something like this:

public void initHandlers() {

   addEventHandler(SFSEventType.USER_LOGIN, UserLoginEventHandler.class);

...

}

And I would need to inject stuff into the UserLoginEventHandler.class. So I don't think assisted inject can help here, can it?



Alper Akture

unread,
Nov 13, 2012, 12:58:01 PM11/13/12
to google...@googlegroups.com, Alper Akture, ced...@beust.com
Thanks, maybe injecting the injector will be good for now, I'll take a look at Christian's message too. I'm a big TestNG fan btw :)

Christian Gruber

unread,
Nov 13, 2012, 1:45:13 PM11/13/12
to google...@googlegroups.com, Alper Akture, ced...@beust.com
I try to avoid injecting the injector where at all possible. It's very
brittle, and moves errors even further into run-time. Not saying it is
never necessary, but I haven't encountered a case where I needed to do
it except to avoid a re-work of a design that needed the re-work anyway.

Christian.

On 13 Nov 2012, at 12:58, Alper Akture wrote:

> Thanks, maybe injecting the injector will be good for now, I'll take a
> look
> at Christian's message too. I'm a big TestNG fan btw :)
>
>
> On Monday, November 12, 2012 7:38:29 PM UTC-8, Cédric Beust ♔
> wrote:
>>
>> Two more thoughts:
>>
>> - It's possible to inject the injector (I had to do this in at least
>> one place in our code base). Not as bad as referencing a static
>> injector,
>> but still not optimal. I think we should create the annotation
>> @Inception
>> for this kind of trick.
>>
>> - In case you missed Christian's message a few days ago, consider
>> defining the factory interface in the same class that it
>> instantiates, in
>> the spirit of "keeping things together". This alleviates the hassle
>> of
>> having to update both your class and your factory signatures when you
>> add
>> @Assisted parameters.
>>
>> --
>> Cédric
>>
>>
>> --
>> Cédric
>>
>>
>>
>>
>> On Mon, Nov 12, 2012 at 6:14 PM, Alper Akture
>> <alper....@gmail.com<javascript:>
>>> wrote:
>>
>>> Thanks Cedric, I totally agree, I don't like using the injector
>>> directly.
>>> I wasn't aware of assisted injection, could be very useful. However,
>>> for
>>> many of my classes I have problems with, I give the framework the
>>> class
>>> name (in an init method that they call), and they do the
>>> instantiation.
>>> Something like this:
>>>
>>> public void initHandlers() {
>>>
>>> addEventHandler(SFSEventType.USER_LOGIN,
>>> UserLoginEventHandler.class);
>>>
>>> ...
>>>
>>> }
>>>
>>> And I would need to inject stuff into the
>>> UserLoginEventHandler.class. So
>>> I don't think assisted inject can help here, can it?
>>>
>>>>
>>>>
>>
>
> --
> You received this message because you are subscribed to the Google
> Groups "google-guice" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/google-guice/-/IR_0JPK9gNwJ.
Reply all
Reply to author
Forward
0 new messages