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.

Reply via email to