Yup. requireAtInjectOnConstructors only limits things that Guice links to constructors. So if you manually new it up within a provider (or @Provides), or if you manually link to a specific constructor (with bind(..).toConstructor(..)), then Guice doesn't require the @Inject annotation.
For requireExplicitBindings, that just makes sure you don't inject things that aren't somehow/somewhere listed in a Module (either as a bind, @Provides, etc..). Basically, if you didn't explicitly say to Guice, "I want <this>", Guice won't let you inject it. sam On Fri, Sep 20, 2013 at 10:12 AM, Nate Bauernfeind < nate.bauernfe...@gmail.com> wrote: > 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 <sber...@gmail.com> 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" <nate.bauernfe...@gmail.com> >> 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 <eched...@gmail.com>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 < >>>> nate.bauernfe...@gmail.com> 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 < >>>>> nate.bauernfe...@gmail.com> 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 >>>>>> <eched...@gmail.com>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 google-guice+unsubscr...@googlegroups.com. >>>>>>> To post to this group, send email to google-guice@googlegroups.com. >>>>>>> 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 google-guice+unsubscr...@googlegroups.com. >>>>> To post to this group, send email to google-guice@googlegroups.com. >>>>> 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 google-guice+unsubscr...@googlegroups.com. >>>> To post to this group, send email to google-guice@googlegroups.com. >>>> 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 google-guice+unsubscr...@googlegroups.com. >>> To post to this group, send email to google-guice@googlegroups.com. >>> 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 google-guice+unsubscr...@googlegroups.com. >> To post to this group, send email to google-guice@googlegroups.com. >> 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 google-guice+unsubscr...@googlegroups.com. > To post to this group, send email to google-guice@googlegroups.com. > 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 google-guice+unsubscr...@googlegroups.com. To post to this group, send email to google-guice@googlegroups.com. Visit this group at http://groups.google.com/group/google-guice. For more options, visit https://groups.google.com/groups/opt_out.