Re: How to inject an interface implementation based on annotations at runtime using Google Guice

85 views
Skip to first unread message

Stephan Classen

unread,
Aug 24, 2014, 6:07:08 PM8/24/14
to google...@googlegroups.com

Guice does not provide a way to bind conditionally. Any decission which is made at runtime must happen in your code.

The only thing which I can think of that might help in this kind of situation are multibindings. Basically multibindings allow to bind many implementations of an interface. All binded implementations can then be injected as a set or map. Your could could then iterate over all implementations and select the correct one for the current input.
https://github.com/google/guice/wiki/Multibindings

Am 23.08.2014 11:52 schrieb Rudolf Visagie <rudolf....@gmail.com>:
I have the following scenario:

    public interface ServiceClientAdapter {
       
SomeData getSomeData()
   
}


   
@LegacyServiceClientAdapter
   
public class MyLegacyServiceClientAdapterImpl implements ServiceClientAdapter {
       
public SomeData getSomeData() {
           
// implementation          
       
}
   
}
   
   
@NewServiceClientAdapter
   
public class MyNewServiceClientAdapterImpl implements ServiceClientAdapter  {
       
public SomeData getSomeData() {
           
// implementation          
       
}    
   
}


   
public class BusinessLogic {
       
@Inject
       
private ServiceClientAdapter serviceClientAdapter;
   
}



LegacyServiceClientAdapter and NewServiceClientAdapter are custom annotations. 

The implementation for the serviceClientAdapter field will be determined at runtime by whether the user has been migrated from the legacy to the new service or not. 

What is the best way to accomplish this dependency injection using Google Guice?

Take into account that different BusinessLogic classes will exist, each with their own (different) ServiceClientAdapter-like interface and corresponding legacy and new implementation classes.

Ideally this should be done with a piece of framework code that can be used across all use cases.

--
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...@googlegroups.com.
To post to this group, send email to google...@googlegroups.com.
Visit this group at http://groups.google.com/group/google-guice.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-guice/16c5a15a-7508-460e-b513-23f22e50d3f5%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tim Boudreau

unread,
Aug 30, 2014, 12:25:02 AM8/30/14
to google...@googlegroups.com
Custom scopes are one way.  Assuming there is a well-defined entry point at which the information you make a SomeData from becomes available, you could do something like 
 - Bind SomeData to a provider that will create it on the fly from whatever you make one from (such as an HTTP request) - call it RawData
 - Your Provider<SomeData> will take a Provider<RawData> as an argument
 - In your Provider<SomeData> you call get() on the Provider<RawData> and make a SomeData and return it
 - When you have a RawData, enter your custom scope, giving it the RawData, so that anything injected while the scope knows about the RawData (usually you put that in a ThreadLocal) will get a SomeData created by your provider
    - Ask the injector to construct the object that takes a SomeData, then use it

I've used this approach to do things like this:
which takes an HTTP request, and lets you pass an interface type, and it will inject a dynamic proxy that implements the interface and fetches data from the URL parameters, for example.

For the custom scope part, I wrote a library that can help: https://github.com/timboudreau/scopes

-Tim

Reply all
Reply to author
Forward
0 new messages