Guice inject interface with thousands of implementation

588 views
Skip to first unread message

klc

unread,
May 13, 2015, 5:26:37 AM5/13/15
to google...@googlegroups.com
Hi guys, 

I have a servlet application that use reflection to find service class, for example a URL:

abc.com/contextroot/asdf?TX=TX1: A servlet is dedicated to 'asdf', it use 'TX1' to lookup the configuration and get service class name, and use Class.forName().newInstance() to get the instance.

Now I want to integrated Guice into this system. And there and thousands of service class.....what's the right way to do it?
I can use annotation binding or @Named, but that will be thousands of class to change...
Can I put the reflection code (.newInstance()) into a provider? but the Provider interface 'get()' has no argument

klc

David

unread,
May 13, 2015, 11:03:37 AM5/13/15
to google...@googlegroups.com
As I recently learned in this group: Guice does not allow n:1 bindings.

So you have an option to either:
- define named bindings for the thousands of service classes
- define a factory class with a method that takes a string and returns the service instance. Then you just need to bind an implementation of the factory that uses your reflection code.

I guess the last option can be enhanced to support injecting dependencies in the service by injecting the Injector in the Factory implementation and using it to get an instance of the service.



--
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/fd20026d-f89e-494a-9180-c07eed9f2f95%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Robert Voliva

unread,
May 13, 2015, 11:14:43 AM5/13/15
to google...@googlegroups.com
Assuming they all implement a common Interface, take a look at MapBinder and/or building a Map instance to inject.  "TX1" would be the key, the class corresponding to that key would be the value.  In your Servlet you would then @Inject the Map.

If you don't know all your implementations, and again assuming they all implement a common Interface or extend a common base Class, you could use something like Guava's ClassPath Class to find all your implementations at startup and add them to the Map.

Jens

unread,
May 13, 2015, 11:31:51 AM5/13/15
to google...@googlegroups.com
I am just guessing as I never tried it but wouldn't the following work (assuming guice-servlet)?

@RequestScoped
public final MyService provideMyService(Injector injector, @RequestParameters Map<String, String[]> requestParams) {
   String txValue = ... // get TX query param value from requestParams
   String className = lookupImplClass(txValue); // same lookup code as before which searches through your configuration
   Class<?> serviceImplClass = Class.forName(className);
   return injector.getInstance(serviceImplClass); // should work because of Just-In-Time bindings
}

And then you inject a Provider<MyService> into your servlet and call service.get() for each request? Since provideMyService() is called for each request it should provide the correct implementation and you can use @Inject in all your service implementations.

-- J.
Reply all
Reply to author
Forward
0 new messages