Hey Sam, That's good to know. Does this allow any provider injection? (both the @Provides annotation in a module and an explicit binding to a provider?)
Thanks, Nate On Thu, Sep 19, 2013 at 11:37 PM, Sam Berlin <[email protected]> wrote: > FYI, if you're looking to prevent injecting things that don't have a > constructor annotated with @Inject, you want to use > requireAtInjectOnConstructors (which I think is only available in the beta > release). requireExplicitBindings requires that there's a bind statement > for the binding, but the thing that is bound doesn't necessarily need an > @Inject constructor (so long as there's a default no-args constructor). > > sam > On Sep 20, 2013 12:02 AM, "Nate Bauernfeind" <[email protected]> > wrote: > >> Hmph, I was using a Module where I called 'requireExplicitBindings' under >> the covers. But it turns out that parameterization does not apply to >> Provider's and you can easily create a provider for something that has a >> default constructor. So, you're right; that is not a viable solution. >> >> Ok, then instead of injecting a provider.. you can inject the injector >> and explicitly grab it yourself. Or, you can construct a provider that >> takes the injector. Here's (seriously) a working example: >> >> class TestModule extends PrivateModule with ScalaPrivateModule { >> def configure() { >> val injector = getProvider[Injector] >> >> bind[B].toProvider(new Provider[B]() { >> def get() = { >> new B(injector.get().instance[A]) >> } >> }) >> >> expose[B] >> } >> } >> >> object TestModule { >> def main(args: Array[String]) { >> val injector = Guice.createInjector(new TestModule) >> println("Successfully created injector.") >> injector.instance[B] >> } >> } >> >> This is the output when run: >> Successfully created injector. >> Exception in thread "main" com.google.inject.ProvisionException: Guice >> provision errors: >> >> 1) Could not find a suitable constructor in A. Classes must have either >> one (and only one) constructor annotated with @Inject or a zero-argument >> constructor that is not private. >> at A.class(TestModule.scala:9) >> while locating A >> at TestModule.bind(TestModule.scala:24) >> while locating B >> >> And again, you can use an annotated @Provides on a method and pass in the >> injector (instead of a provider) as well as inject the injector directly >> into the class. >> >> >> Also, at this point in time, with this solution, it feels very much like >> a work-around than a natural fit for your system. So it's even more obvious >> that you'll probably want to explicitly separate extending the historical >> stuff separate from the broker stuff. >> >> Sorry for the wrong answer earlier. Guice was lying to me (and that >> became more obvious when A didn't have a default constructor)! >> Nate >> >> On Thu, Sep 19, 2013 at 10:13 PM, Eric Tschetter <[email protected]>wrote: >> >>> Hrm, the thing with the suggestion of switching to Providers is that the >>> broker won't even have a binding to a provider, so I'm pretty sure (haven't >>> tried yet) that it will fail out saying that it doesn't know how to create >>> that Provider. >>> >>> I thought about creating separate methods for the different node types, >>> but I'd rather not tie the API to the set of the nodes that exist. I'd >>> prefer to have the system have the freedom to change around how it >>> structures and thinks about nodes without the extensions having to worry >>> about them. >>> >>> I'll try the Provider out tomorrow and see if that fixes it and if that >>> doesn't work (and there aren't other suggestions), I'll start adjusting >>> everything to be under one big injector. >>> >>> --Eric >>> >>> >>> On Thu, Sep 19, 2013 at 9:12 PM, Nate Bauernfeind < >>> [email protected]> wrote: >>> >>>> Also, I might recommend allowing your extensions to implement two >>>> separate configuration methods -- one for the historical injector and the >>>> other for your broker injector. >>>> >>>> Then, something like you're explaining would easily be "covered" or >>>> explained as a bug in the contract between your design and the extension. >>>> >>>> >>>> On Thu, Sep 19, 2013 at 9:10 PM, Nate Bauernfeind < >>>> [email protected]> wrote: >>>> >>>>> I think this is the easiest way to do this (written in Scala purely >>>>> for terseness): >>>>> >>>>> class A >>>>> class B @Inject() (a: A) >>>>> >>>>> class TestModule extends PrivateModule { >>>>> def configure() {} >>>>> >>>>> @Provides >>>>> def createB(a: Provider[A]): B = { >>>>> new B(a.get()) >>>>> } >>>>> } >>>>> >>>>> If you change Provider[A] to A you get the eager binding validation. >>>>> Note, you can still annotate your provider method as a Singleton. >>>>> >>>>> Additionally, you can let your B take in a Provider and have the >>>>> needed logic to error out if an instance of A is not available in your >>>>> injected class' constructor. >>>>> >>>>> Nate >>>>> >>>>> >>>>> On Thu, Sep 19, 2013 at 2:39 PM, Eric Tschetter <[email protected]>wrote: >>>>> >>>>>> Hello Guicers, >>>>>> >>>>>> I'm running into a bit of a problem that I was wondering if someone >>>>>> from the Guice community might have some great insight into how to deal >>>>>> with it. >>>>>> >>>>>> I have a project that is an open distributed analytical data store ( >>>>>> http://www.druid.io) and I've been guicifying it in order to better >>>>>> accommodate plugins. >>>>>> >>>>>> I'm basically using SPI to find instances of a "DruidModule" >>>>>> interface that I created in the classpath of extensions, I then add those >>>>>> modules into the main Guice injector and I'd added an external module to >>>>>> the system. Or, at least, that's the theory. >>>>>> >>>>>> This is generally working, however, I have a number of different node >>>>>> types that each have different object graph requirements. Right now, >>>>>> each >>>>>> node type creates its own injector with modules that build up only the >>>>>> object graph required by that node type. >>>>>> >>>>>> This is causing a problem for my extensions, because I'm only >>>>>> creating a single module in the extension, which can get added to any of >>>>>> the injectors on any of the processes. Specifically, I have a "broker" >>>>>> node and a "historical" node. The extension I'm working with is >>>>>> meaningful >>>>>> in both contexts, but only a subset of the classes are actually used on >>>>>> the >>>>>> "broker" node, while all of them are relevant to the "historical" node. >>>>>> >>>>>> The problem is, the one class that is only used on the historical >>>>>> node (i.e. it is bound by the module, but never instantiated on the >>>>>> broker >>>>>> node), depends on something that the broker node does not have a binding >>>>>> for. Even though the broker node never instantiates the thing that >>>>>> requires the missing binding, Guice still fails because, if it did need >>>>>> it, >>>>>> it wouldn't be there. >>>>>> >>>>>> I've been wondering if there's a way to actively turn off the >>>>>> checking there and force it to be lazy. I don't actually leverage Guice >>>>>> except in the bootstrap phase of my application, so I don't gain any >>>>>> extra >>>>>> benefit from how Guice enforces fail-fast behavior and thus the check >>>>>> right >>>>>> now is only serving as an annoyance :). >>>>>> >>>>>> The only other work-around I can see for this is to basically build >>>>>> one big Guice injector with full bindings for use across all node types. >>>>>> The only differentiation between the node types being the set of objects >>>>>> that actually get instantiated on startup. If I were to do that, I would >>>>>> work around this, but it would also open the door to having weird things >>>>>> accidentally instantiated at weird points, so I'm a little reluctant to >>>>>> do >>>>>> it. If this is the only option, I will switch to this model, just hoping >>>>>> there are other options as well. >>>>>> >>>>>> Does that all make sense? >>>>>> >>>>>> --Eric >>>>>> >>>>>> -- >>>>>> 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 [email protected]. >>>>>> To post to this group, send email to [email protected]. >>>>>> Visit this group at http://groups.google.com/group/google-guice. >>>>>> For more options, visit https://groups.google.com/groups/opt_out. >>>>>> >>>>> >>>>> >>>> -- >>>> 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 [email protected]. >>>> To post to this group, send email to [email protected]. >>>> Visit this group at http://groups.google.com/group/google-guice. >>>> For more options, visit https://groups.google.com/groups/opt_out. >>>> >>> >>> -- >>> 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 [email protected]. >>> To post to this group, send email to [email protected]. >>> Visit this group at http://groups.google.com/group/google-guice. >>> For more options, visit https://groups.google.com/groups/opt_out. >>> >> >> -- >> 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 [email protected]. >> To post to this group, send email to [email protected]. >> Visit this group at http://groups.google.com/group/google-guice. >> For more options, visit https://groups.google.com/groups/opt_out. >> > -- > 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 [email protected]. > To post to this group, send email to [email protected]. > Visit this group at http://groups.google.com/group/google-guice. > For more options, visit https://groups.google.com/groups/opt_out. > -- 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 [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/google-guice. For more options, visit https://groups.google.com/groups/opt_out.
