Russ,

I appreciate you taking the time to respond.  Unfortunately I'm afraid
I don't understand enough about using child injectors to make your
suggestion work, though I did try.

Ultimately my implementation above fails because I don't have a way to
tell the factory generated by FactoryProvider.newFactory() to use the
CImpl implementation for C without explicitly creating that binding.
But creating that binding exposes a new problem, because Guice doesn't
know how to inject an @Assisted annotated value outside of the
assistinject framework, as detailed in the response to this
stackoverflow post:

http://stackoverflow.com/questions/1595723/how-to-bind-assisted-injected-class-to-interface

The simplest solution for me at this point is to (sadly) abandon Guice
for the creation of this object.  I can do the following and make it
work:

class CFactory {
    public C create( D d ) {
        return new CImpl( d );
    }
}

class B {
    @Inject CFactory cFac;

    void executeB( D d ) {
        cFac.create( d ).executeC();
    }
}

In this approach, CImpl is completely outside Guice's control, but it
allows me to pass in my runtime D implementation without confusing
Guice.  Not my first choice, but I thank everyone for the
suggestions.  If anyone has further thoughts, feel free to share.

Thanks,
Ryan

On Dec 9, 9:20 am, Russ Milliken <[email protected]> wrote:
> One other option is the use of a child injector, rather than a custom
> scope.  I'm sorry that I don't have time to elaborate but perhaps someone
> else on this list could.
>
> Basically, in the place where you need the custom (or different) binding you
> could create a child injector from the main one, overriding the default
> binding in a custom module and passing this to the child injector via
> Modules.override().
>
> -Russ
>
>
>
>
>
>
>
> On Thu, Dec 9, 2010 at 9:40 AM, Ryan <[email protected]> wrote:
> > Fred,
>
> > Thank you for the prompt response!  I spent some time last night
> > playing with your suggestion, and I was able to get it to work.
> > However, I was hoping to find a solution that didn't require the extra
> > work of a custom scope, with the intrusion of the framework into my
> > domain code.  This is not a webapp, and using RequestScoped doesn't
> > really make sense in this context either.
>
> > I'm wondering if there's a possible solution that could be confined to
> > annotations and the Provider interface alone, with the rest of the
> > configuration in modules.  Am I barking up the wrong tree?
>
> > Thanks,
> > Ryan
>
> > On Dec 8, 5:49 pm, Fred Faber <[email protected]> wrote:
> > > When I hear that a dependency depends on a runtime value I immediately
> > think
> > > about binding the value in scope.  You can then manually seed the value
> > > upstream before you traverse the downstream call graph.
>
> > > Something like:
>
> > > D d = getD();
> > > simpleScope.seed(D.class, d);
> > > doSomethingThatRequiresD();
>
> > > ...
>
> > > class DependsOnD {
> > >  // Inject a provider this class is created before D is in scope
> > >   @Inject Provider<D> dProvider;
> > >   ...
> > >   void useD() {
> > >      dProvider.get().doSomething();
> > >   }
>
> > > }
>
> > > ...
>
> > > // Or you might have your own scope
> > > bind(D.class).in(RequestScoped.class);
>
> > > -Fred
>
> > > On Wed, Dec 8, 2010 at 7:42 PM, Ryan <[email protected]> wrote:
> > > > Hello everyone,
>
> > > > Been an avid user of Guice for a while now, and just ran across a new
> > > > situation that has me stumped.  I've got a dependency that I need to
> > > > be able to change at runtime.  The catch is, the piece of code that
> > > > needs it is far down the call graph from where it changes.  I've
> > > > attempted to use assisted inject to let me customize the object at
> > > > runtime, but there's a hitch.
>
> > > > An example will make this more clear:
>
> > > > class MyModule extends AbstractModule {
> > > >    protected void configure() {
>
> > > > bind( BFactory.class ).toProvider( FactoryProvider.newFactory(
> > > > BFactory.class,
> > > > B.class ) );
> > > >    }
> > > > }
>
> > > > interface BFactory {
> > > >    B create( D d );
> > > > }
>
> > > > class A {
> > > >   �...@inject BFactory bFac;
>
> > > >    void executeA( D d ) {
> > > >        bFac.create( d ).executeB();
> > > >    }
> > > > }
>
> > > > class B {
> > > >   �...@inject C c;
>
> > > >    void executeB() {
> > > >        c.executeC();
> > > >    }
> > > > }
>
> > > > class C {
> > > >   �...@inject @Assisted D d;
>
> > > >    public void executeC() {
> > > >        System.out.println( d );
> > > >    }
> > > > }
>
> > > > class D {};
>
> > > > Now I can call A.executeA() with different instances of D (which is
> > > > needed by C) at runtime.  Executing the above classes with the
> > > > following code,two different D objects are written to stdout as
> > > > expected:
>
> > > > A a = i.getInstance( A.class );
> > > > a.executeA( new D() );
> > > > a.executeA( new D() );
>
> > > > This works as long as I only create C through the BFactory, and as
> > > > long as everything is concrete.  But if I introduce an interface,
> > > > there's a problem, as follows:
>
> > > > class MyModule extends AbstractModule {
> > > >    protected void configure() {
>
> > > > bind( BFactory.class ).toProvider( FactoryProvider.newFactory(
> > > > BFactory.class,
> > > > B.class ) );
> > > >        bind( C.class ).to( CImpl.class );
> > > >    }
> > > > }
>
> > > > interface C {
> > > >    void executeC();
> > > > }
>
> > > > class CImpl implements C {
> > > >   �...@inject @Assisted D d;
>
> > > >    public void executeC() {
> > > >        System.out.println( d );
> > > >    }
> > > > }
>
> > > > This gives me an error:
>
> > > > 1) No implementation for D annotated with
> > > > @com.google.inject.assistedinject.Assisted(value=) was bound.
> > > >  while locating D annotated with
> > > > @com.google.inject.assistedinject.Assisted(value=)
> > > >    for field at CImpl.d(AssistedInjectTest.java:62)
> > > >  at MyModule.configure(AssistedInjectTest.java:28)
>
> > > > The BFactory binding is still okay, but the C->CImpl binding is what
> > > > produces the error.  I assume this is because class C could
> > > > conceivably be wired into another class as a dependency (in addition
> > > > to class B) and Guice wouldn't know what to do with the dependency on
> > > > D.
>
> > > > What's the best solution to this?  Am I making it needlessly complex?
> > > > I need to know if there's a way to supply D to C without B knowing
> > > > anything about it, while still allowing A to change what D is.
>
> > > > Thanks,
> > > > Ryan
>
> > > > --
> > > > You received this message because you are subscribed to the Google
> > Groups
> > > > "google-guice" group.
> > > > To post to this group, send email to [email protected].
> > > > To unsubscribe from this group, send email to
> > > > [email protected]<google-guice%2bunsubscr...@google
> > > >  groups.com>
> > <google-guice%2bunsubscr...@google groups.com>
> > > > .
> > > > For more options, visit this group at
> > > >http://groups.google.com/group/google-guice?hl=en.
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "google-guice" group.
> > To post to this group, send email to [email protected].
> > To unsubscribe from this group, send email to
> > [email protected]<google-guice%2bunsubscr...@google 
> > groups.com>
> > .
> > For more options, visit this group at
> >http://groups.google.com/group/google-guice?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-guice?hl=en.

Reply via email to