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.

Reply via email to