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.

Reply via email to