Injection of context in a @Provides method ?

213 views
Skip to first unread message

Mikkel Petersen

unread,
Mar 7, 2014, 5:13:50 PM3/7/14
to google...@googlegroups.com
Hello all 

I have a slight problem with guice injection when using a method annotated with  @Provides

example :

@Provides
public Service someService() {
 return new SomeService()
}

I would like to get the current context injected in SomeService..I don't understand why Guice doesn't do that automatically, any particular reason for that ?

I know I could do something like this (it works):

@Provides
public Service someService(@Inject Injector inj)  {
  SomeService s =  new SomeService()
  inj.injectMembers(s)
  return s
}

But there must be a simpler way.

Thanks

Ps, another question, how to add syntax highlighting ?





Nate Bauernfeind

unread,
Mar 7, 2014, 5:32:42 PM3/7/14
to google...@googlegroups.com
What about your use case prevents you from using a normal .to binding?

bind(SomeService.class).to(SomeService.class)

Nate


--
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/d/optout.

Mikkel Petersen

unread,
Mar 7, 2014, 5:44:40 PM3/7/14
to google...@googlegroups.com
Because I want to receive other bindings:
public Service someService(@Inject Settings settings)  {
  SomeService s =  new SomeService(settings.getHost())
  inj.injectMembers(s)
  return s

Sam Berlin

unread,
Mar 7, 2014, 5:53:40 PM3/7/14
to google...@googlegroups.com
Your service can receive other bindings by having them injected into its constructor.  If the class is defined as:
 class  SomeService {
   @Inject SomeService(Settings settings) { ... }
 }

.. then when others inject the service, Guice will create it with the correct dependencies for you.

Is there some reason you're unable to inject the parameters directly into the constructor (and are forced to use 'new')?

 sam

Nate Bauernfeind

unread,
Mar 7, 2014, 5:54:17 PM3/7/14
to google...@googlegroups.com
It's a bit more work, but you could consider using assisted injection for this kind of use-case. My typical pattern looks like this:

public class Example {
    @Inject
    public Example(@Assisted("host") String host
                   HttpClient httpClient,
                   ...) {
       ...
    }

    /** This class is a Guice Assisted-Inject Factory. */
    public static interface Factory {
        Example newExample(@Assisted("host") String host);
    }
}

...

public class ExampleModule {
  void configure() {
    bindFactory(Example.class, Example.Factory.class);
  }

  protected <T, F> void bindFactory(Class<T> klass, Class<F> factoryKlass) {
        bindFactory(klass, klass, factoryKlass);
   }
}

And then you can still use a provider method (if you prefer!) and then you inject the factory and the settings.

@Provides
public Example someExample(Example.Factory factory, Settings settings) {
  return factory.newExample(settings.getHost());
}

Hope that helps! I use this pattern a lot, but not often mixed with a Provider -- usually I have a class that manages the multiple instances key'ed by some name (like client or user).

Nate Bauernfeind

unread,
Mar 7, 2014, 5:56:47 PM3/7/14
to google...@googlegroups.com
Oops, I apologize, I left off this other method on the module (these methods are in generic abstract modules that I inherit from, one that extends from AbstractModule and the other from PrivateModule):

protected <T, F> void bindFactory(Class<T> source, Class<? extends T> klass, Class<F> factoryKlass) {
  install(new FactoryModuleBuilder().implement(source, klass).build(factoryKlass));
}

Mikkel Petersen

unread,
Mar 7, 2014, 6:00:00 PM3/7/14
to google...@googlegroups.com
Thanks for your response.

It's seems overly complicated and I must admit, I don't understand it fully..though it properly works..I fail to see the usage of @Provides methods if the object provided doesn't have the object graph injected.

Nate Bauernfeind

unread,
Mar 7, 2014, 6:07:22 PM3/7/14
to google...@googlegroups.com
@Provides are typically when you need to inject an instance of some library out of your control that doesn't have any guice bindings. I try to avoid using providers for any other use case. In your specific example, I would do what Sam suggested and just simply inject the Settings object.

I use dropwizard a lot and typically finding myself creating hierarchical configuration objects, and passing the sub-configuration object to a specific module. For example,

class ApplicationConfiguration {
  public DatabaseConfiguration data;
  public TwitterConfiguration twitter;
  ...
}

And then they map one-to-one to a top-level PrivateModule which accepts the sub-configuration object as part of its constructor. Then I can easily either inject the configuration class privately for that sub-portion of my application, or do whatever I need to with it (like configure an http client in a @Provides method).

Happy Guicing! 

Mikkel Petersen

unread,
Mar 7, 2014, 6:16:49 PM3/7/14
to google...@googlegroups.com
Thank you all for your responses !

Problem is, my application has grown to the point that even the modules themselves have becoming an application.

So there are many objects created in different modules, needed by others...

What I really need is to be able to inject dependencies into module.

The ideal solution would be 
TestModule extends Module   {
   Inject SomeObjectCreatedInAFarWayModule someObject; 
 }

But that is not possible, so because of that I took a look at providers, which allow dependencies to be injected into modules.
My application has at least 100 modules by now, and growing.
So far I have used static public objects, but as everyone knows, that is bad practice.

Nate Bauernfeind

unread,
Mar 7, 2014, 7:08:14 PM3/7/14
to google...@googlegroups.com
I can't say that I've ever dealt with an experience of having 100+ unique modules (now if you want to talk about 100+ child injectors created from different instances of the same module (i.e. as a template)... now that I've done). I think my largest experience has sliced things up into maybe 15 modules; which is still quite a handful to manage.

The biggest thing that I did that helped managed dependency relationships across modules was to prefer PrivateModules over completely public AbstractModules. It made me really think about what each module was being used for and what it exposed for use with the rest of the application. For example, I don't mind creating a different ExecutorService that might be used in an entire sub-graph that is not shared across all of my modules. In fact, limiting how portions of your application can interact, or interfere, with each other can dramatically improve your experience when debugging or fine-tuning certain things. 

Perhaps, migrating and merging some of your modules to each have a specific purpose might bring things back to being manageable and meaningful for you.

Additionally, I've had some experience here and there using Guava's EventBus to further decouple sub-systems by instead communicating with messages. For example instead of injecting the TwitterService and have every listener register itself as a listener, I instead can use the EventBus to subscribe to all messages of a type "TwitterEvent" and then the messages get to the right places behind the scenes on my behalf (you only need to add an @Subscribe assuming you let guice register your objects). This works well for data that flows as opposed to data that you need to pass back an answer (though I've tried this too by passing a settable Future as a means of a lightweight callback -- but I wasn't extremely satisfied, nor unsatisfied, with the result). The applications that I have that use an event bus can typically remove a guice module from the list that gets passed into the injector and everything will still start up and run appropriately -- just no one will get any TwitterEvents if that module was removed.

Mikkel Petersen

unread,
Mar 7, 2014, 7:18:42 PM3/7/14
to google...@googlegroups.com
I have already optimized each and every module..I have spent years doing that, really. But they still run into the exact same problem that Guice was supposed to solve: how do we get object A to object B.
With hundreds of modules, that problem will occur over and over..For example, I have a list of Listeners in Module A. Module A binds them, plus add some listener code to the list. Module XYZ23B now wants to add a listener to this list as well. How ? Only solution right now is to have a class that references this list public and statically. Now, you could say, my logic is wrong. All logic concerned this listener list should be in one module..but perhaps the two do not have much in common logic wise than this object.

Sam Berlin

unread,
Mar 7, 2014, 7:22:37 PM3/7/14
to google...@googlegroups.com
I don't understand why your modules need things injected.  The point of modules is to set up rules saying "this is bound to that" and "when someone wants this, give them that".  It does not require knowing the interrelationships of each object.  I highly suspect there's something fundamentally wrong with your setup, but it's hard to say for certain without knowing what you're doing.

 sam

Mikkel Petersen

unread,
Mar 7, 2014, 7:33:06 PM3/7/14
to google...@googlegroups.com
It's hard for me to describe the entire problem..I was really just looking for a solution to this, now it has turned into something else. But fine, I'll try to explain my point further.

Lets say its not fully possible to populate an object just from Module, that other modules should have access to this object as well in order for it to be fully ready for use.

For example, we have an object NameList

Module A {
 configure() {
      nameList = new NameList()
      bind(NameList.class).toInstance(nameList)
      name = new Name("peter")
       requestInjection(name)
      nameList.add(name)
   }
}

Module B {
   Name name = new Name("James")
   requestInjection(name)
   nameList.addName(name)
   
}

Module B binds a new name, injects it, and adds it to the NameLIst. But the namelist was created and bound in module A !! How will it get a reference to NameList ?
We could do something like this 

GuiceStatics {
   public static NameList nameList
}
And access it from here. Or make a singleton factory or whatever.  But why ? this is what Guice helps us to avoid !

Point is, the entire module section of any application can grow into something huge itself. And because of that, it needs dependency injection itself.

Sam Berlin

unread,
Mar 7, 2014, 9:45:59 PM3/7/14
to google...@googlegroups.com

I hate to break it to you, but it increasingly looks like you're making this much harder for yourself, using the framework in a way it's not intended.

For this particular problem (adding things to a shared pool), there's an extension called Multibinder: http://code.google.com/p/google-guice/wiki/Multibindings .

For other issues, you may want to consider asking for specific guidance and help in StackOverflow (or searching for existing questions/answers).  I suspect you'll find that things will become a lot simpler.

sam

Mikkel Petersen

unread,
Mar 8, 2014, 9:51:21 AM3/8/14
to google...@googlegroups.com
Are you suggestion I should google around and ask ? thanks, would have never thought about that..

Mikkel Petersen

unread,
Mar 8, 2014, 9:54:17 AM3/8/14
to google...@googlegroups.com

Btw, Multibindings doesnt solve this..but I'm glad that you told me I do things wrong, without telling me why, and without providing an alternative solution. Did you even look at the sample ?

Sam Berlin

unread,
Mar 8, 2014, 9:56:16 AM3/8/14
to google...@googlegroups.com
I suggested going specifically to StackOverflow, which is a website devoted to programming questions/answers.

Additionally, I suggested a solution of Multibindings, which AFAICT is specifically for the problem you outlined.

If you have further problems, I'm not sure I can help much more, though others on this list may be able to.

 sam

Mikkel Petersen

unread,
Mar 8, 2014, 10:02:56 AM3/8/14
to google...@googlegroups.com

Well multiibindings solves, in a way, the listener problem. Because it works on sets. But it doesnt solve if I wanted to access other objects from other modules.
If you could care to explain to me why this is "wrong" without saying "its just wrong" I'm all ears.
You might as well say that using a injection framework is wrong because injection is a sign that the logic in your application is wrong.
I'm not convinced at all that my clam is not legitimate but we can  disagree on that, no problem. I'll simply note that at this point, Guice can't handle this problem.

Nate Bauernfeind

unread,
Mar 8, 2014, 11:11:57 AM3/8/14
to google...@googlegroups.com

It does depend on how you're doing your listener pattern, but Guava's EventBus might be a nice alternative, like I explained in an earlier email.

I think Sam was just pointing out that it seems like you're using Guice in an unintended way. Which can decrease the satisfaction of your particular experience.

Which, of course is a shame, because Guice has been an amazing experience for me, and I won't do any project without it.

It should technically be possible to have a two stage dependency injection setup. I've personally toyed with the idea as a way to decouple configuration from the application (before I started using dropwizard I used multiple json files that would auto inject @Named strings). It should work in your case as well if you name your collections and inject them into your modules.

So the idea is that the first injector is created to instantiate all modules, so you would need very few super modules that binds each of your original modules. You will likely want to use multibinder to register each module so that you can pull them directly off of this initial injector to construct the second phase injector.

It should work and may help with the problem you've found yourself in.

If you feel like you can share a handful of module source files with me, out of thread, I'd be happy to see if there are even better and more concrete suggestions I can give you.

Nate

Mikkel Petersen

unread,
Mar 8, 2014, 4:19:35 PM3/8/14
to google...@googlegroups.com
Yes, but project was started before eventbus existed. Stil, I would like to make the conversion.
I too thought about the "inject modules first" solution. I think its a bit silly though, and smells like a workaround from something that should be a lot easier to do.

Mikkel Petersen

unread,
Mar 8, 2014, 4:21:17 PM3/8/14
to google...@googlegroups.com

Also, the modules that configures the module might grow in complexity..then what ? make another module that configures the module that configures the module ?

Mikkel Petersen

unread,
Mar 8, 2014, 4:34:23 PM3/8/14
to google...@googlegroups.com

Mikkel Petersen

unread,
Mar 8, 2014, 10:37:43 PM3/8/14
to google...@googlegroups.com
Too bad this has to be unresolved. Google ignores it, for  some weird reason.


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/HMj5hmPjmR4/unsubscribe.
To unsubscribe from this group and all its topics, 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/d/optout.



--
Med venlig hilsen/Best regards

Mikkel Petersen

Jagtvej 82 4th
2200 København N
Telefon  35 37 63 10
Mobil 91 97 03 64

Christian Gruber

unread,
Mar 9, 2014, 12:38:23 AM3/9/14
to google...@googlegroups.com
I'm going to point out that "Google" doesn't ignore this thread -
"Google" as a corporation does not offer any guarantees or warrantees or
service-level-agreements with respect to Guice, which is clear in the
Apache license attached to every file.

You asked a question on a developer community list, got answers, and you
didn't think those answers addressed your issue. Fair enough. Engineers
from Google and elsewhere who care about this framework, and who work
very hard (but are not being paid with a Guice support contract), have
answered your questions as best they can, but there is a disconnect.
That happens. It may not be resolvable if you want to use Guice in a
different way than how it was designed. They offered you alternative
resources, and you have those in hand.

This list cannot be the place to teach someone Guice from whole-cloth.
It can contribute to someone learning how to use Guice, but there are
patterns for which Guice was intended, and things that are outside its
scope or design basis. Very experienced Guice developers are telling
you you are trying to do something in a way that Guice wasn't set up
for. That is not insignificant counsel.

There are limits to what one can communicate over a mailing list of this
format. Please consider this, and consider how much un-obligated
engineers have spent of Google's (and other firms') salaried time to
help you. Certainly the matter isn't closed if there are any folks on
this list who wish to help... but I agree with Sam - StackOverflow is
actually a much better system than a mailing list to handle this sort of
thing - as it has better tools for expressing sample code, answers can
be given and voted on and commented. It is a reasonable suggestion to
take the question to that forum. Other Google projects (and also
companies like Square, etc.) are moving more and more of this sort of
list discussion over to stack overflow. Please do not consider it a
brush off, but a sincere recommendation of a more fruitful course of
action.

regards,
Christian.

On 8 Mar 2014, at 22:37, Mikkel Petersen wrote:

> Too bad this has to be unresolved. Google ignores it, for some weird
> reason.

Christian Gruber :: Google, Inc. :: Java Core Libraries :: Dependency
Injection
email: cgr...@google.com :::: mobile: +1 (646) 807-9839

Mikkel Petersen

unread,
Mar 9, 2014, 12:31:12 PM3/9/14
to google...@googlegroups.com
Why do this list even exists then ? Of course I was looking for a response and a solution, I was just a little surprised that people would spent more energy trying to look for errors in my code instead of addressing the issue.
A simple "No, what you're trying to do is not possible, try alternatives"..would have been enough.


--
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/HMj5hmPjmR4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to google-guice+unsubscribe@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/d/optout.

Christian Gruber

unread,
Mar 9, 2014, 7:43:46 PM3/9/14
to google...@googlegroups.com

You bring up a good point... Why does this list exist?  It existed prior to the fantastic take off of the stack exchange platform and so we should consider the modern purpose of this list.  Thank you for pointing out this mis-match of purposes.

I will start a separate thread to discuss the purpose of this list and ways to better curate its content, ways to steer people to the best resources, and how we can publicize that.  This was very useful feedback upon consideration.

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.

Nate Bauernfeind

unread,
Mar 10, 2014, 3:26:26 PM3/10/14
to google...@googlegroups.com
Just finished reading through the stack overflow link; thanks for sharing it. It reminded me of the following:

I've heard/read/adopted the policy that guice modules should sincerely avoid any conditional logic. If you do find yourself with some conditional logic try and split your module up by either moving the conditional logic into a provider or up into multiple modules and let your application choose which module(s) based on the appropriate mode(s). It's hard to do, and I probably don't have one project that is conditional free in all configure methods... but that certainly helps defer the need to inject some things into a guice module.

Next, I wanted to point out one pattern I've used quite often when it comes to registering objects for some purpose (like listening to events, or even to enable key-based delegation to that object). Typically you'll have a main service you want to register to listen/subscribe on, which I'll use the example of a DaoService. Users of the DaoService can subscribe to the Dao to listen for events that occur on any sub-class of a type. So some handwaving:

class DaoService {
   public synchronized void addListener(Class<T> type, DaoListener<T> listener) {...}
}

public interface DaoListener<T> {
    public void dataAdded(T data) throws Exception;
    public void dataUpdated(T oldData, T newData) throws Exception;
    public void dataRemoved(T data) throws Exception;
}

And then in my user class (and sometimes this is an abstract base class) I use setter injection specifically to register the listener:

class ExampleUser {
  private Listener _listener = new Listener();

  @Inject
  public ExampleUser(...) {...}

  @Inject
  private void registerAsDaoListener(DaoService service) {
    service.addListener(MyDataType.class, _listener);
  }
  
  private final class Listener implements DaoListener<MyDataType> {
    ...
  }
}

So, again, in this example I'm decoupling the idea of who is listening to what data. Obviously the sender / daoService needs to be around (unlike in the event bus example), but now no one ever needs to know about how many listeners there are (depending on how you store your listeners you may need to make sure you're not overwriting any other listener in the addListener method).

And.. I also use Scala as often as I can, so sometimes pieces of these end up in a trait that is easy to mix-in for the repeated functionality (like managing the listener map/list).

So.. maybe this would be a good alternative to the multibinding extension for you. I've used it with great success (esp. when the register method is on an abstract base class).

Good luck and happy Guicing =),
Nate

Mikkel Petersen

unread,
Mar 10, 2014, 4:15:41 PM3/10/14
to google...@googlegroups.com
This sounds like a good idea but wont to get a "Already bound" exception ?

Nate Bauernfeind

unread,
Mar 10, 2014, 4:27:38 PM3/10/14
to google...@googlegroups.com
No actually you don't get already bound exceptions. Guice actually treats the injection as a setter based injection (it doesn't care how you name methods; but I tend to use the word register since it seems to suggest not saving the object). 

So if you're thinking on the Abstract case you'd have something like this:

abstract class AbstractThing {
  @Inject
  private void registerThing(ThingService service) { service.registerThing(this) }
}

class Thing1 extends AbstractThing {
...
}

class Thing2 extends AbstractThing {
...
}

and in your configure method you can just do:

bind(Thing1.class).asEagerSingleton()
bind(Thing2.class).asEagerSingleton()

And the magic just happens. It doesn't matter if Thing1/Thing2 are in the same module or separate modules as long as the ThingService exists somewhere and are being created as part of the same injector. And note that the private classifier allows you to hide the fact that Guice is going to do this for you. So you never have to worry about users of Thing1/Thing2 abusing that method (at-least I like making it private; your milage may vary =P).

If you bind AbstractThing to Thing1 and to Thing2 you will get an already bound exception. But the AbstractThing class doesn't need to show up in any bindings for the injection to occur.

Good luck,
Nate

--

Mikkel Petersen

unread,
Mar 10, 2014, 4:38:54 PM3/10/14
to google...@googlegroups.com
That makes a lot of sense, thanks. I'm not sure it will solve all scenarios..but lets see. 

Mikkel Petersen

unread,
Mar 10, 2014, 5:36:27 PM3/10/14
to google...@googlegroups.com
Still, since not all classes are injectable (third party) you might need to access them and populate them manually..


Den mandag den 10. marts 2014 21.27.38 UTC+1 skrev Nate Bauernfeind:

Mikkel Petersen

unread,
Mar 10, 2014, 6:11:36 PM3/10/14
to google...@googlegroups.com
in case anyone has the same problem..this is my solution so far (a real world example)

class WorldPhysXModule extends Module {
  val world: WorldPhysX = new WorldPhysX
  @Provides
  @Singleton
  @Named("dimensionScale") def dimensionScale(settings: IProperties): Float =  settings.getFloat("dimensionScale")

  @Provides
  @Singleton
  def provideWorld(settings: IProperties) = {
    val subStep1: Float = 1f / settings.getFloat("subStep1")
    val subStep2: Int = settings.getInt("subStep2")
    world.setGravity(0, settings.getFloat("gravity"), 0)
    world.setTiming(subStep1, subStep2)
    world.setStepSize(settings.getFloat("stepSize"))
    world.setEnableContactUserReport(true)
    world;
  }
  def configure(binder: Binder) {
    binder.requestInjection(binder)
    binder.requestInjection(world);
    binder.bind(classOf[GroundPlaneActor]).toInstance(new GroundPlaneActor(world, "groundPlane", 1000, 0.00f))
  }

}

Note that "WorldPhysx" does not know anything about guice, so we have to access the setters directly..
To ensure that also "World" gets injected, call requestInjection in configure but dont BIND it here..do that in provides..anyway that's my fifty cent.

Nate Bauernfeind

unread,
Mar 10, 2014, 6:21:41 PM3/10/14
to google...@googlegroups.com
It's nice to see another scala fan. You may consider checking out scala-guice ... some helper stuff that makes guice more scala friendly. https://github.com/codingwell/scala-guice

It seems odd that you're extending Module directly; I think I've only ever needed to use AbstractModule or PrivateModule. Also, since, world doesn't have any guice annotations, then you shouldn't need to call requestInjection on it; since that should be a no-op. I also don't think you need to request injection on the binder... it seems out of place from my experience.

Nate

Sam Berlin

unread,
Mar 10, 2014, 6:28:52 PM3/10/14
to google...@googlegroups.com
FYI, injecting a MembersInjector<World> into the '@Provides provideWorld' and calliing injectMembers(world) will remove the need to do the requestInjection in configure.

 sam

Mikkel Petersen

unread,
Mar 10, 2014, 6:37:33 PM3/10/14
to google...@googlegroups.com
Im not sure what you mean could you post a small example ?

Mikkel Petersen

unread,
Mar 10, 2014, 6:40:31 PM3/10/14
to google...@googlegroups.com
How else would I create a module unless I subclassed  it ?  binder.requestInjection(binder) is an error, dont know why its there (it didnt do anything, good or bad though:)

You're right, why would I inject World if theres nothing to inject ? well, my argument lists gets smaller and smaller:)
Anyway, this is how to do it, if one wants to do it..

Sam Berlin

unread,
Mar 10, 2014, 6:41:47 PM3/10/14
to google...@googlegroups.com
@Provides provideFoo(MembersInjector<Foo> fooInjector) {
   Foo foo = new Foo();
   fooInjector.injectMembers(foo);
   return foo;
 }

Also answered here.

 sam

Mikkel Petersen

unread,
Mar 10, 2014, 6:43:22 PM3/10/14
to google...@googlegroups.com
The latest example, with garbage removed

class WorldPhysXModule extends AbstractModule {
  val world: WorldPhysX = new WorldPhysX
  @Provides
  @Singleton
  @Named("dimensionScale") def dimensionScale(settings: IProperties): Float =  settings.getFloat("dimensionScale")

  @Provides
  @Singleton
  def provideWorld(settings: IProperties) = {
    val subStep1: Float = 1f / settings.getFloat("subStep1")
    val subStep2: Int = settings.getInt("subStep2")
    world.setGravity(0, settings.getFloat("gravity"), 0)
    world.setTiming(subStep1, subStep2)
    world.setStepSize(settings.getFloat("stepSize"))
    world.setEnableContactUserReport(true)
    world;
  }
  def configure  {
    requestInjection(world);

--
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/HMj5hmPjmR4/unsubscribe.
To unsubscribe from this group and all its topics, 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/d/optout.



--

Mikkel Petersen

unread,
Mar 10, 2014, 6:44:21 PM3/10/14
to google...@googlegroups.com
Oh yes im normally also extending AbstractModule. I was trying something else out..so just ignore that..


Den mandag den 10. marts 2014 23.21.41 UTC+1 skrev Nate Bauernfeind:

Mikkel Petersen

unread,
Mar 10, 2014, 6:48:16 PM3/10/14
to google...@googlegroups.com
Thanks sam..thats usefull


--
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/HMj5hmPjmR4/unsubscribe.
To unsubscribe from this group and all its topics, 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/d/optout.



--

Dirk Olmes

unread,
Mar 10, 2014, 9:31:10 PM3/10/14
to google...@googlegroups.com
On 03/10/2014 09:27 PM, Nate Bauernfeind wrote:
> No actually you don't get already bound exceptions. Guice actually
> treats the injection as a setter based injection (it doesn't care how
> you name methods; but I tend to use the word register since it seems to
> suggest not saving the object).
>
> So if you're thinking on the Abstract case you'd have something like this:
>
> abstract class AbstractThing {
> @Inject
> private void registerThing(ThingService service) {
> service.registerThing(this) }
> }
>
> class Thing1 extends AbstractThing {
> ...
> }
>
> class Thing2 extends AbstractThing {
> ...
> }
>
> and in your configure method you can just do:
>
> bind(Thing1.class).asEagerSingleton()
> bind(Thing2.class).asEagerSingleton()

Great trick. But now you're left with pointless Thing1 and Thing2
instances in the Injector. For only 2 instances that's not worth the
hassle but in my case they may become hundreds ...

-dirk

Nate Bauernfeind

unread,
Mar 11, 2014, 1:08:55 AM3/11/14
to google...@googlegroups.com

Interesting! Have you found a significant performance overhead? I tend to hide bindings like these in a private module, but I doubt that would make their cost any cheaper. Can you explain what the cons are from this approach? I do things like this all the time now.

Thanks,
Nate

Dirk Olmes

unread,
Mar 12, 2014, 2:29:38 PM3/12/14
to google...@googlegroups.com
> On 03/10/2014 09:27 PM, Nate Bauernfeind wrote:
> > No actually you don't get already bound exceptions. Guice actually
> > treats the injection as a setter based injection (it doesn't care how
> > you name methods; but I tend to use the word register since it
> seems to
> > suggest not saving the object).
> >
> > So if you're thinking on the Abstract case you'd have something
> like this:
> >
> > abstract class AbstractThing {
> > @Inject
> > private void registerThing(ThingService service) {
> > service.registerThing(this) }
> > }
> >
> > class Thing1 extends AbstractThing {
> > ...
> > }
> >
> > class Thing2 extends AbstractThing {
> > ...
> > }
> >
> > and in your configure method you can just do:
> >
> > bind(Thing1.class).asEagerSingleton()
> > bind(Thing2.class).asEagerSingleton()
>
> Great trick. But now you're left with pointless Thing1 and Thing2
> instances in the Injector. For only 2 instances that's not worth the
> hassle but in my case they may become hundreds ...
>
> Interesting! Have you found a significant performance overhead? I tend
> to hide bindings like these in a private module, but I doubt that would
> make their cost any cheaper. Can you explain what the cons are from this
> approach? I do things like this all the time now.

Before adopting an approach that you describe I try to think about the
"cost" of it. In your case that's additional instances bound to the
injector and retained throughout the entire lifetime of the Injector. Im
my case that's as long as the app lives.

Now an object here and there and a few extra bindings might be worth the
decoupling you gain from this approach.

-dirk

Nate Bauernfeind

unread,
Mar 12, 2014, 5:35:58 PM3/12/14
to google...@googlegroups.com
I agree. If these objects weren't meant to exist throughout the life of my application then binding them as singletons is not a good idea. Additionally, you wouldn't want the listener subscription to last forever either. I instead move subscribe and unsubscribe into start and stop methods. In cases like this I have found two options for injection. For most cases I use an AssistedInject factory since I still want guice injections but I'll typically create multiple instances keyed by something (like user or client). On a recent project I actually wanted to create a rich sub-graph of objects per client, so I actually created a childInjector where I had a 'ServiceName' token bound and I was able to remove most of the assisted inject factories. I injected those objects as eager singletons in the childInjector, but without the registerThing injection. Instead I call start and stop on every object in the subgraph as a client was being provisioned and deprovisioned.

So, I guess I don't mind paying for the increased start-up time and the extra map entries if it means I don't have to do any manual dependency management.

I also wouldn't call this pattern a decoupled pattern. IMO, this is still quite coupled. The listener has to 1) implement an interface defined by the service (either directly, with a static inner class, or use some arbitrary implementation) and 2) it has to inject the service that it wants to listen to (which the pattern I showed tries to hide). So the listener still has to know enough of the service.

A decoupled approach would be the eventbus solution I talked about earlier in the thread; in that case both parties only need to know about the event bus and the message models/types. In this model it doesn't matter who's generating the content or who's consuming the content. Whereas in the case where the service maintains a listener list/mapping then there really can only be one generator.

Nate



-dirk

Mikkel Petersen

unread,
Mar 25, 2014, 4:18:59 PM3/25/14
to google...@googlegroups.com
Actually found an incredible simple way to do this:

def  configure() {
var a  = someObj()
val dummyObj = new Object {
      @Inject
      def whateverName(f: TheDependency) = {
          f.add(a)
      }
    }
     requestInjection(dummyObj );
  }



--
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/HMj5hmPjmR4/unsubscribe.
To unsubscribe from this group and all its topics, 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/d/optout.
Reply all
Reply to author
Forward
0 new messages