Runtime dependent implementations

270 views
Skip to first unread message

Ryan

unread,
Nov 18, 2009, 12:02:24 AM11/18/09
to google-guice
Hello everyone,

I'm new to Guice (really enjoying it, by the way), but have come up
against a need and I'm not sure the most Guice-appropriate way to do
it. Done a lot of searching (including in this group), but am not
sure I found the solution. (Or perhaps I just didn't understand it.)
In any case, my question is how to select an implementation based on
some runtime value. For reference, a standard factory solution would
look like:

class ServiceFactory {
public static Service get(int type) {
if(type == 1) { return new ServiceImpl1(); }
else if (type == 2) { return new ServiceImpl2(); }
}
}

class Client {
public void process(int type) {
Service service = ServiceFactory.get(type);
}
}

Feels too service locator-y. But I can think of no way to do this in
Guice except to inject the factory:

class Client {
@Inject
ServiceFactory factory;

public void process(int type) {
Service service = factory.get(type);
}
}

class ServiceFactoryProvider implements Provider<ServiceFactory> {
@Override
public ServiceFactory get() {
return new ServiceFactory();
}
}

class MyModule extends AbstractModule {
@Override
protected void configure() {
bind(Client.class);
}
}

What am I missing here? What's the proper way to implement this with
Guice? I don't think BindingAnnotations will work for me here,
because the implementation is decided upon at runtime, but feel free
to correct me.

Thank you!
Ryan

Gary Pampara

unread,
Nov 18, 2009, 12:37:29 AM11/18/09
to google...@googlegroups.com
You should have a look at the assisted inject extension:

http://code.google.com/p/google-guice/wiki/AssistedInject
> --
>
> You received this message because you are subscribed to the Google Groups "google-guice" group.
> To post to this group, send email to google...@googlegroups.com.
> To unsubscribe from this group, send email to google-guice...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/google-guice?hl=.
>
>
>

Ryan

unread,
Nov 18, 2009, 9:31:40 AM11/18/09
to google-guice
Gary,

I looked at AssistedInject before, but I don't think that will work.
AssistedInject is good for an implementation that requires runtime
parameters, but you are still binding the factory to a single concrete
implementation. I need to be able to actually choose my
implementation at runtime. If there's a way to do that, please feel
free to show me.

I also looked at Multibindings, which seems like it might work, but
then my client still has to do the work: iterating to find the right
implementation.

Ryan

Sam Berlin

unread,
Nov 18, 2009, 9:38:49 AM11/18/09
to google...@googlegroups.com
Will there always be one implementation and only one implementation for the lifetime of the project?  If so, can you decide upon that implementation during runtime before the Injector is created?  If so, include the appropriate module to bind the ServiceImpl you want based on the configuration.  If the impl can change throughout the lifetime (because users can request different types based on the 'type'), then you'll absolutely need some form of indirection (in your code the Factory provides the indirection).  If you're concerned about calling new Service1 & new Service2, you can use BindingAnnotations to actually bind both kinds of Services, the Factory can have both Services injected and then hand out the appropriate service based on the 'type'.

Sam

Gary Pampara

unread,
Nov 18, 2009, 10:23:47 AM11/18/09
to google...@googlegroups.com
Sorry I see now what you mean. Where do you get the information
regarding the 'type' so that the factory can create the needed
instance?

I solved this a while ago in a project using the builder pattern. This
is a trivial example, but it seems to work. If anyone has a better way
of doing this, I'd appreciate the advice.

http://pastie.org/704247

Brian Pontarelli

unread,
Nov 18, 2009, 10:31:41 AM11/18/09
to google...@googlegroups.com
Just need to be careful of state and provider use if you go with a builder pattern.

Another way I've handled this in the past is using dynamic proxies that use the method parameters to perform a lookup. In the end, all the solutions I've used are the same. There is at least one level of indirection and someone has to perform a lookup or build a new instance (i.e. a provider). In the lookup case the Injector can be used to perform the lookup. In the provider case I've used post-inject after instantiation or pre-injection of the provider.

-bp

Gary Pampara

unread,
Nov 18, 2009, 10:38:26 AM11/18/09
to google...@googlegroups.com
Agreed the state could be a problem. You could probably get around it
by directly passing in the value to avoid managing the state.

Would naturally be great to find a solution that "is always best".

Ryan

unread,
Nov 18, 2009, 11:49:05 AM11/18/09
to google-guice
@Sam:

Yes, the Impl can be changed throughout the lifetime of the project,
so I will need some sort of Factory. I was simply hoping there was a
better way of having Guice provide it. I assume with your 2nd
suggestion, you're talking about something like this?

class ServiceFactory {
@Inject ServiceImplA serviceImplA;
@Inject ServiceImplB serviceImplB;

public Service get( int type ) {
if ( type == 1 ) {
return serviceImplA;
} else if ( type == 2 ) {
return serviceImplB;
}
return null;
}
}

That works, although I don't know if I'm fond of requiring that all
implementations be instantiated each time the ServiceFactory is
instantiated.

@Gary:

The "type" is external to the application. I've simplified the use
case obviously, but the client is an object that gets spun up during
an HTTP request. The underlying dependencies (impls) that it needs
will depend on what's in the request. Think Command pattern.

Your builder pattern would work great if I could pass the type to the
get() method, rather than to the provider constructor. But Guice
doesn't support that as a valid Provider<T> implementation.

@Brian:

Can you give me an example of using dynamic proxies, as you explained?

This seems like a fairly common use case, so I'm surprised there isn't
a better pattern to handle it. Thanks everyone for your prompt
responses so far.

Ryan

On Nov 18, 8:38 am, Gary Pampara <gpamp...@gmail.com> wrote:
> Agreed the state could be a problem. You could probably get around it
> by directly passing in the value to avoid managing the state.
>
> Would naturally be great to find a solution that "is always best".
>
>
>
> On Wed, Nov 18, 2009 at 5:31 PM, Brian Pontarelli <br...@pontarelli.com> wrote:
> > Just need to be careful of state and provider use if you go with a builder pattern.
>
> > Another way I've handled this in the past is using dynamic proxies that use the method parameters to perform a lookup. In the end, all the solutions I've used are the same. There is at least one level of indirection and someone has to perform a lookup or build a new instance (i.e. a provider). In the lookup case the Injector can be used to perform the lookup. In the provider case I've used post-inject after instantiation or pre-injection of the provider.
>
> > -bp
>
> > On Nov 18, 2009, at 8:23 AM, Gary Pampara wrote:
>
> >> Sorry I see now what you mean. Where do you get the information
> >> regarding the 'type' so that the factory can create the needed
> >> instance?
>
> >> I solved this a while ago in a project using the builder pattern. This
> >> is a trivial example, but it seems to work. If anyone has a better way
> >> of doing this, I'd appreciate the advice.
>
> >>http://pastie.org/704247
>
> >> For more options, visit this group athttp://groups.google.com/group/google-guice?hl=.

Sam Berlin

unread,
Nov 18, 2009, 12:08:14 PM11/18/09
to google...@googlegroups.com
That works, although I don't know if I'm fond of requiring that all
implementations be instantiated each time the ServiceFactory is
instantiated.


If that's the only issue with that pattern, then you're in luck!  You don't need to instantiate the impls when a factory is instantiated.  Instead of injecting the Impl itself, inject a Provider<Impl> and return yourProviderA.get() or yourProviderB.get().  That will cause the impl to be constructed on-demand (assuming the impl is not an eager singleton).

Sam
 

Ryan

unread,
Nov 18, 2009, 12:46:42 PM11/18/09
to google-guice
Sam, that was just what I needed. Thanks a ton!

Brian Pontarelli

unread,
Nov 18, 2009, 5:09:42 PM11/18/09
to google...@googlegroups.com
> @Brian:
>
> Can you give me an example of using dynamic proxies, as you explained?

You create a dynamic proxy that implements your interface and then the MethodHandler does a lookup based on the parameters passed in. Looks roughly like:

Service s = Proxy.newProxy(Service.class, new MyHandler());
bind(Service.class).toInstance(s);

class MyHandler implements MethodHandler {
Object call(Object[] params) {
if (params[0].equals("foo")) {
Service realService = ...; // Do lookup here
return realService.doSomething((String) params[0]);
}
...
}
}

This uses the parameters passed in to the service to do the lookup and find the correct implementation to use. It then invokes the real service and passes the parameters along.

I like this pattern and it could be wired into Guice. Be nice to do something like:

bind(Service.class).toProxy(MyServiceProxy.class);

Service s = Injector.newInstance(Service.class);
s.doSomething(42);

class MyServiceProxy implements Proxy<Service> {
@Inject FourtyTwoService fourtyTwoService;
... // Other implementations could be injected here

Service lookup(Object[] args) {
// Do lookup here using arguments passed to the service
int number = (int) args[0];
if (number == 42) {
return fourtyTwoService;
}
...
}
}

Guice would use the proxy to find the real instance and then invoke the real instance instead. This is essentially the same as above, but everything is wired together and handled by Guice.

-bp

Ryan

unread,
Nov 18, 2009, 10:45:36 PM11/18/09
to google-guice
Brian,

Thank you for the example. One question: as I was trying to follow
your example, I couldn't locate a Proxy class that accepts a
generified type (Proxy<T>). I assume the class you're using there is
the one in java.lang.reflect? Or is it a Guice class that I've missed
somehow?

In any case, your pattern there looks very similar to the one Sam
suggested, so I think I get the idea.

Ryan

Brian Pontarelli

unread,
Nov 19, 2009, 10:28:25 AM11/19/09
to google...@googlegroups.com
The first code snippet is all in the JDK. It uses the java.lang.reflect.Proxy class to handle everything. This class dynamically implements interfaces at runtime and uses a MethodHandler (or something like that) to handle call to the dynamic implementation of the interface.

The second code snippet is just some thoughts on a Guice enhancement that would provide the same type of functionality without using the java.lang.reflect.Proxy. None of the code in the second code snippet currently exists.

-bp
Reply all
Reply to author
Forward
0 new messages