Coding for Multiple Implementaions for a service without named annotaions in GUICE

2,087 views
Skip to first unread message

sreenivasu puppala

unread,
Feb 19, 2014, 6:55:11 AM2/19/14
to google...@googlegroups.com
Hi Group,

           Need a suggestion for how to code for multiple implementations for a service using Google-guice. Below is the example


           TestService testService =new TestServiceImplOne();
           TestService testService =new TestServiceImplTwo();


           As Guice doesn't allow to bind a type to more than one implementations as the below code results in error

           binderObject.bind(SomeType.class).to(ImplemenationOne.class);
           binderObject.bind(SomeType.class).to(ImplemenationTwo.class);

           we can solve this with named annotations as below

           binder.bind(Player.class).annotatedWith(Names.named("Good")).to(GoodPlayer.class);
           binder.bind(Player.class).annotatedWith(Names.named("Bad")).to(BadPlayer.class);

          @Named("Good") Player goodPlayer = (Player)injector.getInstance(Player.class);
          @Named("Bad") Player badPlayer = (Player)injector.getInstance(Player.class);


           But the application which iam working is something like this


           we are binding all the modules in the init() method and creating the injector modules
          
           //sepertae method to bind
           protected void configure() {
                    bind(new TypeLiteral<List<Service>>() {
                    }).toInstance(serviceSets);
                }

           //seperate method to inject
           Injector i = Guice.createInjector(modules);  //


        But with the above process I can just bind one Implementation class to the interface(service class)


        Could you please provice me a way to do this with providers. I would like to do something like this below

        class  TestServiceProvider extends Provider{

           /// some code where it returns the  instance of impl class needed. In my case TestServiceImplOne and TestServiceImplTwo and provider returns the corresponding instance of service class

        }

    
      and bind service class with provider class. Something like this

      bind(TestService.class).toProvider(TestServiceProvider.class);

      May be iam talking something baseless , iam sorry if iam doing that but this is my requirement, i would  appreciate if someone suggest me a good example using providers or some other way where i can inject whatever implementation i want in the client.


      Note: Iam using webservices and iam absolutley not sure how i can inject different implementations when a webservice is called to a serviceclass .


    Thanks very much
    Sreenivasu
     








          




          

Tim Boudreau

unread,
Feb 20, 2014, 12:30:52 AM2/20/14
to google...@googlegroups.com
You can do things like this with Guice 4's ProvisionListener.  I did that once, so that classes or packages could be annotated with a "namespace" that determined where properties they wanted injected would be loaded from, to allow some legacy code I was helping rearchitect code to migrate off of hard-coded paths to things and manually loading configuration.  See this: http://j.mp/1dPIuGN

That being said, I've kind of regretted adding that feature ever since :-)

But I don't think you need anything so general or complex.

It's not clear from your post what you want to switch on to decide which implementation to provide.  You don't want to use @Named, but *something* has to choose which thing to inject.  So, where does the information live, which is used to decide that?  And does it change at runtime?

If it doesn't change at runtime, just give yourself a command-line argument or whatever equivalent makes sense for what you're doing (your class names above suggest some kind of test mode, but I'm guessing).  Have @ImplementedBy pointing to a mock implementation, and only install the module that binds the real implementation if that flag is not there (or is there, whatever you want).

If it's something more fancy, I don't think anyone can help you without knowing what information should be used to decide what to inject, and what part of the application has it.  If you know what that is, all you need to do is write a Provider that uses it.

-Tim

sreenivasu puppala

unread,
Feb 24, 2014, 6:15:13 AM2/24/14
to google...@googlegroups.com
First of all thanks very much Tim for responding and sorry for not giving the detailed information. Coming straight to the point

Iam working on webservices . Heres's the Flow

GET   http://localhost:8182/indi/provide/organizations/{ou}


OrganizationsResource -------->OrganizationService------>OrganizationServiceImpl
    
Iam binding OrganizationService with OrganizationServiceImpl and injecting the OrganizationService in OrganizationsResource

@Inject
    public void setOrganizationService(OrganizationService orgService) {
        this.orgService= orgService;
    }


Its fine till here but i have two implementations for OrganizationService --------->OrgDeatilsServiceImpl which does some other job

Now i want to bind both OrganizationServiceImpl and OrgDeatilsServiceImpl to OrganizationService

Confusions:

1) What procedure i have to use in Guice to bind two implementaions?
2) How exactly i can code in OrganizationsResource  to dynamically decide which implementation to call.


I would appreciate if you give a sample example for the above requirement. 


Many thanks again for the quick reply and awaiting your response on this mail.


Thanks
Sreni

Moandji Ezana

unread,
Feb 24, 2014, 6:52:32 AM2/24/14
to google...@googlegroups.com

If you need a specific implementation and can determine which one you need, I would inject both concrete classes into OrganizationResource and not have to do anything fancy.

--
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.
For more options, visit https://groups.google.com/groups/opt_out.

sreenivasu puppala

unread,
Feb 24, 2014, 9:51:35 AM2/24/14
to google...@googlegroups.com
Thank you !! 

Can i get a sample example ? 
Well, thats a good idea to inject concrete classes into the resource . Could you also please send an example and if possible could you also please tell me whether there any other ways of doing this?

Thanks
Sreeni

Stephan Classen

unread,
Feb 24, 2014, 10:01:47 AM2/24/14
to google...@googlegroups.com
If you feel uncomfortable injecting the concrete instances you can delegate the responsibility to choose the correct instance to a provider/helper.
The provider gets all concrete instances injected and has a method getServiceFor(...) which returns the correct instance.
You have to pass to the method getServiceFor(...) the information which is needed to make the decision which instance to choose.

sreenivasu puppala

unread,
Feb 24, 2014, 12:52:29 PM2/24/14
to google...@googlegroups.com
Thanks , I would like to go with providers. Could you please post me the sample code like how can i configure my concrete classes with providers and how can i code the same to get the instance in resource class in my case OrganizationResource.

It will really help me to code i have a sample in place for the above example.

Stephan Classen

unread,
Feb 25, 2014, 3:06:34 AM2/25/14
to google...@googlegroups.com
public class OrganizationServiceProvider {

private final OrganizationServiceImpl orgService;
private final OrgDeatilsServiceImpl orgDetailService;

@Inject
OrganizationServiceProvider(final OrganizationServiceImpl
orgService, final OrgDeatilsServiceImpl orgDetailService) {
this.orgService = orgService;
this.orgDetailService = orgDetailService;
}

public OrganizationService getServiceFor(/* you must pass the the
necessary input to decide which impl to choose */) {
// your code goes here. it must return either orgService or
orgDetailService
}
}

public class OrganizationsResource {

private final OrganizationServiceProvider osProvider;

@Inject
OrganizationsResource(final OrganizationServiceProvider osProvider) {
this.osProvider = osProvider;
}

// more code...
}

There is no special binding in the Guice module necessary since all
injections go to concrete classes.
Of course it would be nice to introduce an interface for
OrganizationServiceProvider and have an OrganizationServiceProviderImpl.
In this case you would need to bind the impl to the interface.

Juan Pablo Vergara Villarraga

unread,
Feb 26, 2014, 6:38:57 AM2/26/14
to google...@googlegroups.com
I understand the solution from scl as a container for all the possible implementations of the dependency to be injected. It looks like a practical solution when there are few implementations. Would it be an elegant solution if we have a hundred implementations or so?

Im currently coding a solution for this problem as well. If I find a different solution I'll post it :)

JP

sreenivasu puppala

unread,
Feb 26, 2014, 9:35:31 AM2/26/14
to google...@googlegroups.com
I agree with you JP  , it would be very difficult to accomodate if there are hundred implementations , Please post me if you find any solution, iam in need of the code urgently :-)


Thanks SCL, i have question

I guess OrganizationServiceProvider should implement Provider in the below code?

Stephan Classen

unread,
Feb 27, 2014, 1:22:25 AM2/27/14
to google...@googlegroups.com
Question1 - 10+ implementations:
If you have lots of implementation or you have a plugin like architecture where new implementations may be added after your main component has already been released then my proposed solution would not scale. If you are in such a situation have a look at multibinders: http://code.google.com/p/google-guice/wiki/Multibindings
But if you are sure you will only have a very limited number of implementations and no new ones will be added after release day I would go with an approach similar to my proposal. Simply because I feel it is easier readable and most important it is testable without having to create an injector.

Question2 - should it implement Provider<T>:
I deliberately did not implement the provider interface. And if you would try to add it to my code you would get a compiler error.
I prefer to pass the required data to make the decision which implementation to choose to the method getServiceFor(...).
The provider interface on the other hand has only a no-arg method get(). If you would want to implement the provider interface you would have to inject all required information to make the decision into your implementation. This may lead to more complex code when the decision is based on a user action or similar information which is not available beforehand.
I agree that in a guice based implementation the usage of the word provider in a class name may not be well suited if the class does not implement the provider interface.
You could call the class OrganizationServiceFactory or OrganizationServiceLocator to avoid confusion.
--

Paweł Cesar Sanjuan Szklarz

unread,
Mar 3, 2014, 5:06:50 AM3/3/14
to google...@googlegroups.com
Hi.

For the "hundred of implementations" problem, You can use custom scopes to select on runtime the binding that should be used. Final code may look like this:

public class LogicThatUseTheSelectedService {

@Inject
private Provider<Service> selectedServiceProvider;

@AnnotationToBindServiceSelection
public void makeTheWork(){
   Service selectedService = selectedServiceProvider.get();
   ....
}
}

To make it work, You need to:
-- Make a custom scope that will have a reference to the binded service in runtime (a ThreadLocal<Service>)
-- make a aspect for the annotation @AnnotationToBindServiceSelection that will find and setup the desired service (on base of the current runtime context) in the custom scope.

A very similar example is provided in my post "Controlled Scope"

The difference is that the calls "controller.setupBusinessContext.." and "controller.clearBusinessContext()" in the method "businessOperation" will be extracted to the annotation aspect. Your final implementation of BusinessContextController will be:
public interface BusinessContextControl {
 
 void setupBusinessContext(Service selectedService);
  
 void clearBusinessContext();
}

If you need any more details, just let me know.

Pawel Cesar Sanjuan Szklarz.




Reply all
Reply to author
Forward
0 new messages