In my application there are multiple modules binding something to a specific name or class. Is there a way to tell Guice, which modules it should use when resolving the dependencies to inject.
My simplified dependency graph looks something like this where blue indicates classes from module 1 and red indicates classes from module 2. Now I want to create two instances from the A class, but with different classes bound to some dependencies.
public class Module1 extends AbstractModule {
#Override
protected void configure() {
bind(C.class).to(C_Impl1.class)
bind(D.class).to(D_Impl1.class)
}
}
public class Module2 extends AbstractModule {
#Override
protected void configure() {
bind(C.class).to(C_Impl2.class)
bind(D.class).to(D_Impl2.class)
}
}
public class Application {
#Inject #UseModules(Module1, ...) private final A someClassUsingImpl1;
#Inject #UseModules(Module2, ...) private final A someClassUsingImpl2;
public void doSomethingWithImpl1() {
someClassUsingImpl1.doSomething()
}
public void doSomethingWithImpl2() {
someClassUsingImpl2.doSomething()
}
}
This is the problem private modules were built for. You will still need to use a binding annotation to differentiate whether you're asking for the Impl1 version of A or the Impl2 version of A.
/** Marks Impl1 classes. Inject #Impl1 A to get A using C_Impl1 and D_Impl1. */
#BindingAnnotation
#Retention(RetentionPolicy.RUNTIME)
#interface Impl1 {}
/** Marks Impl2 classes. Inject #Impl2 A to get A using C_Impl2 and D_Impl2. */
#BindingAnnotation
#Retention(RetentionPolicy.RUNTIME)
#interface Impl2 {}
/** This is now a PrivateModule. Only exposed bindings can be used outside. */
public class Module1 extends PrivateModule {
#Override
protected void configure() {
// Bind C and D as you had before.
bind(C.class).to(C_Impl1.class);
bind(D.class).to(D_Impl1.class);
// Here's the tricky part: You're binding "#Impl1 A" to
// "A" without a binding annotation, but only in here.
bind(A.class).annotatedWith(Impl1.class).to(A.class);
// Now you expose #Impl1 A, so it can be used outside.
// As long as A, C, and D are only bound within private modules,
// they won't conflict with one another, and #Impl1 A is unique.
expose(A.class).annotatedWith(Impl1.class);
}
}
/** Treat Module2 the same way, as a private module. */
public class Application {
#Inject #Impl1 private final A someClassUsingImpl1;
#Inject #Impl2 private final A someClassUsingImpl2;
// ...
}
If this is a common pattern for you, create a general PrivateModule that takes in the classes that vary as constructor parameters, so you don't need to repeat yourself. These can be added to the top-level injector, or installed within other modules.
Injector injector = Guice.createInjector(new YourMainModule(),
new ImplModule(Impl1.class, C_Impl1.class, D_Impl1.class),
new ImplModule(Impl2.class, C_Impl2.class, D_Impl2.class));
Related
I have an Interface and multiple implementation. I'm auto wiring the interface in classes for usage. I need to choose different implementation at runtime.
public class Util {
public void getClient();
}
Implementations
public class UtilOne implements Util {
public void getClient() {...}
}
public class UtilTwo implements Util {
public void getClient() {...}
}
#Configuration
public class AppConfig {
#Autowired
#Bean
#Primary
public Util utilOne() {
return new UtilOne();
}
#Autowired
#Bean
public Util utilTwo() {
return new UtilTwo();
}
}
#Component
public class DemoService {
#Autowired
private Util util;
}
For some reason if we are unable to get client in UtilOne, I want to switch to UtilTwo without restarting the app. I want to change the Util object in DemoService to UtilTwo object.
Property active.util will come from DB and can we updated from UI.
It doesn't work this way - if you have a certain implementation of Util wired to, say, class SampleClass (which is a singleton) you can't really change the implementation of the Util to something different without restarting the application context.
So instead of going this way, I suggest an alternative. You say that under certain conditions that evaluate in runtime you want to switch implementations. What kind of condition it is? Is it possible to extract this condition decision logic?
If so, you can autowire a special DynamicUtil that will hold the reference to all the utils and will call the required util depending on the condition:
// represents all possible business 'runtime' outcomes
enum ConditionOutcome {
A, B, C
}
interface ConditionEvaluator {
ConditionOutcome evaluate(); // when called in runtime will evaluate a condition that currently exists in the system
}
interface Util {
void foo();
ConditionOutcome relevantOfOutcome();
}
class Utill1Impl implements Util {
public void foo() {...}
public ConditionOutcome relevantOfOutcome() {return ConditionOutcome.A;}
}
class Utill2Impl implements Util {
public void foo() {...}
public ConditionOutcome relevantOfOutcome() {return ConditionOutcome.B;}
}
class Utill3Impl implements Util {
public void foo() {...}
public ConditionOutcome relevantOfOutcome() {return ConditionOutcome.C;}
}
class DynamicUtil {
private final Map<ConditionOutcome, Util> possibleImpls;
private final ConditionEvaluator evaluator;
public class DynamicUtil(List<Util> allImplementations, ConditionEvaluator evaluator) {
// create a map by calling the 'relevantOfOutcome' per util impl in a loop
this.evaluator = evaluator;
}
public void foo() {
ConditionOutcome key = evaluator.evaluate();
// pick the relevant implementation based on evaluated key
possibleImpls.get(key).foo();
}
}
Now with such a design you can dynamically add new possible outcomes (along with utils that should implement them. You classes in the system will have to autowire DynamicUtil though, so effectively you'll introduce one additional level of indirection but will gain flexibility
class SampleClass { // a business class that will need to work with util capable of being changed during the runtime
#Autowired
private DynamicUtil util;
...
}
You can try approach with delegating proxy. Have a primary Util bean that is just wrapper around actual implementation and allow to change its internal delegate at runtime. In addition you can create something like manager/helper class that holds references to all actual implementation beans to simplify switching between them.
#Component
#Primary
public class DelegatingUtil implements Util {
private Util delegate;
public void setDelegate(Util delegate){ this.delegate = delegate; }
public Util getDelegate(){ return delegate; }
public void getClient() {
return delegate.getClient();
}
}
And where switching logic applies:
// Use #Named or #Qualifier or any other way to obtain references to actual implementations
private Util defaultImpl;
private Util fallbackImpl;
#Autowired
private DelegatingUtil switcher;
public void switchToFallback(){
this.switcher.setDelegate(this.fallbackImpl);
}
Note, this is only schematic example, you should take care about details like bean creation order, injection with qualifiers (maybe conditional), initialization and so on.
Here is a simple approach based on your situation. The main idea is that read active.util property from DB by PropertyService and wrap your Utils into RouteUtil:
#Component
public class RouteUtil {
#Autowired
private PropertyService propertyService;
#Qualifier("one")
#Autowired
private Util utilOne;
#Qualifier("two")
#Autowired
private Util utilTwo;
public void getClient() {
if ("one".equals(propertyService.read("active.util"))) {
utilOne.getClient();
} else {
utilTwo.getClient();
}
}
}
and in DemoService:
#Service
public class DemoService {
#Autowired
private RouteUtil util;
// RouteUtil.getClient() ...
}
You can change active.util to select which Util will be used at runtime without restarting the app.
Spring provides you a solution which I personally didn't like. What you can do is declare a
#MyInterface
List<MyIntercase> myimpls
Where MyInterface is your interface and list will contain all the implementations. However, I (since I didn't like this solution) wrote my own solution, where you can have a static factory that is self-populated by all implementations. So you don't have to inject all your implementations but choose them at run-time from a factory either by class name or by custom-defined name. An additional advantage is that the custom-defined name must be unique per factory. So lets say you have some staged process and for each stage you have your own interface and your own factory. So you can have the same custom defined names for your implementations of different interfaces. Say you working with text formats XML, JSON and CSV and have an interface (and related factory) for say stage-1 stage-2 stage-3. So for each stage-X inteface you can have implemetations named JSON, XML and CSV so all you have to do is have a variable called currentType that will hold one of the values - JSON, XML and CSV and for each stage you can use the factory to get the appropriate implementation:
Stage1Handler handler = stage-1-factory.getInstance(currentValue);
Stage2Handler handler = stage-2-factory.getInstance(currentValue);
Stage3Handler handler = stage-3-factory.getInstance(currentValue);
where Stage[X]Handler is your interface. But this is just an additional benifit. My solution is available in Open-source MgntUtils library. The article about this particular fiture could be found here: Non-intrusive access to "Orphaned" Beans in Spring framework Also, I describe this feature in my library javadoc here. The library could be found as Maven artifact and on Github including source code and Javadoc
I'm learning Google Guice. Do you know how to implement the "robot legs" problem? Let me explain this with an example.
Let's say that I have some class called Service:
#Singleton
public class Service {
#Inject
Source source;
}
The interface Source has two implementations:
public class SourceDatabase implements Source {
}
public class SourceFileSystem implements Source {
}
My module is implemented like this:
public class MyModule extends AbstractModule {
#Override
protected void configure() {
bind(Service.class).asEagerSingleton();
}
}
Well, I would like to know if this is possible:
public class MainClass {
#Inject #SomeAnnotation("database")
Service serviceWithADatabaseSource;
#Inject #SomeAnnotation("file-system")
Service serviceWithAFileSystemSource;
}
Does exist some annotation or binding that let me do that, let me annotate a member like serviceWithADatabaseSource, and this helps Guice to know that the internal member source should be injected with the SourceDatabase implementation?
Edit: Thanks to Daniel Martin, for give us the name of this kind of problem on his comment.
As documented in the Guice Wiki, you need to install two PrivateModules, each of which exposes a Service with the right annotation for you.
public class MyModule extends AbstractModule {
#Override
protected void configure() {
install(new PrivateModule() {
#Override public void configure() {
// Bind Source to SourceDatabase.
bind(Source.class).to(SourceDatabase.class);
// Bind #Named("database") Service to Service.
bind(Service.class).annotatedWith(Names.named("database"))
.to(Service.class);
// Now expose #Named("database") Service without exposing
// either of the other two conflicting bindings.
expose(Service.class).annotatedWith(Names.named("database"));
}
});
install(new PrivateModule() {
#Override public void configure() {
// Same as above.
bind(Source.class).to(SourceFileSystem.class);
bind(Service.class).annotatedWith(Names.named("file-system"))
.to(Service.class);
expose(Service.class).annotatedWith(Names.named("file-system"));
}
});
}
}
If the modules were not PrivateModule instances, those bindings to Source and Service would conflict with one another. However, instead, each binding inherits all the public bindings from the Injector but only exposes the #Named(...) Service to the outside world. This way the same Service implementation can inject the same non-annotated Source but have it return different fully-injected types.
Also note that you will not be able to ask for a Source or Service (without an annotation) outside of the PrivateModules, because you haven't established a binding in any non-private Module. This should be expected: The PrivateModule bindings shouldn't conflict with any public bindings, and without entering through one of the PrivateModule's exposed bindings, Guice won't know which Source or Service to return.
Finally, given that Module instances can take constructor parameters, it may be a good idea to extract the two anonymous inner PrivateModules into a named equivalent:
public class MyModule extends AbstractModule {
#Override
protected void configure() {
install(new SourcePrivateModule(SourceDatabase.class, "database"));
install(new SourcePrivateModule(SourceFileSystem.class, "file-system"));
}
}
I have never used guice before, and I wanted to try it out on an example project with jersey based JAX-RS API backed by a service-bean. I followed this guide: http://randomizedsort.blogspot.de/2011/05/using-guice-ified-jersey-in-embedded.html and was able to bring it to work. My setup is very simple, a JAX-RS resource is invoked via Guice and has a field that is annotated #Inject and injected by Guice:
#Path("configuration")
#Produces(MediaType.APPLICATION_JSON)
#Singleton
public class ConfigurationResource {
#Inject
private ConfigurationService configurationService;
So far so good, everything works like it should, besides following: I am using GuiceServletContextListener for setting things up and have to name each component explicitly:
#WebListener
public class GuiceInitializer extends GuiceServletContextListener{
#Override
protected Injector getInjector() {
return Guice.createInjector(new JerseyServletModule() {
#Override
protected void configureServlets() {
//resources
bind(ConfigurationResource.class);
//services
bind(ConfigurationService.class).to(ConfigurationServiceImpl.class);
// Route all requests through GuiceContainer
serve("/management/*").with(GuiceContainer.class);
}
});
}
}
I find it pretty inconvenient to explicitly name all dependencies. I have worked with standalone jersey before and it's perfectly capable of auto-scanning for resources in defined packages. Also Spring and CDI are capable of mapping implementation to interfaces without need to explicitly name them.
Now the question part:
is there any autoscan extension/setting for guice? I found some on the internet, but it's hard to tell which of them are still useable and uptodate.
is there any other possibility to make configuration of implementations and resources more convenient?
thanks in advance.
Leon
I do not think Guice has built in support for someting like the component-scan of Spring framework. However, it is not difficult to simulate this feature in Guice.
You simply need to write a helper module like the following
import com.google.inject.AbstractModule;
import org.reflections.Reflections;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* To use this helper module, call install(new ComponentScanModule("com.foo", Named.class); in the configure method of
* another module class.
*/
public final class ComponentScanModule extends AbstractModule {
private final String packageName;
private final Set<Class<? extends Annotation>> bindingAnnotations;
#SafeVarargs
public ComponentScanModule(String packageName, final Class<? extends Annotation>... bindingAnnotations) {
this.packageName = packageName;
this.bindingAnnotations = new HashSet<>(Arrays.asList(bindingAnnotations));
}
#Override
public void configure() {
Reflections packageReflections = new Reflections(packageName);
bindingAnnotations.stream()
.map(packageReflections::getTypesAnnotatedWith)
.flatMap(Set::stream)
.forEach(this::bind);
}
}
To component scan a package like com.foo and sub packages for classes carrying #Singleton, use it in this way:
public class AppModule extends AbstractModule {
public void configure() {
install(new ComponentScanModule("com.foo", Singleton.class));
}
}
I understand how to inject a single dependency using Google Guice.
The following snippets are from the Guice site.
To code a configuration the code would be
public class BillingModule extends AbstractModule {
#Override
protected void configure() {
bind(TransactionLog.class).to(DatabaseTransactionLog.class);
bind(CreditCardProcessor.class).to(PaypalCreditCardProcessor.class);
}
}
The component which use the dependencies to be injected shuold looks like the following:
class BillingService {
private final CreditCardProcessor processor;
private final TransactionLog transactionLog;
#Inject
BillingService(CreditCardProcessor processor,
TransactionLog transactionLog) {
this.processor = processor;
this.transactionLog = transactionLog;
}
public Receipt chargeOrder(PizzaOrder order, CreditCard creditCard) {
...
}
}
FInally, the client code would use Guice to inject the dependencies where needed:
public static void main(String[] args) {
Injector injector = Guice.createInjector(new BillingModule());
BillingService billingService = injector.getInstance(BillingService.class);
...
}
My question is:
Is there a built-in feature in Guice to inject not only -for example- BillingService.class but another different implementation in runtime?
I think I can implement the variation of the different classes to be injected thru reflection or some manual mechanism like reading a configuration file to indicate which class to inject but I still want to know if this can be done from Guice itself.
You can make BillingService an interface and bind a different implementation of it decided in runtime in Module's configure method.
I have the following code using Guice bindings:
public class MyApplication {
public static void main(String[] args) {
Guice.createInjector(new AbstractModule() {
#Override
protected void configure() {
bind(Foo.class).annotatedWith(Names.named("first")).toInstance(new Foo("firstFoo"));
bind(Foo.class).annotatedWith(Names.named("second")).toInstance(new Foo("secondFoo"));
bind(Bar.class).to(BarImpl.class);
bind(MyApplication.class).asEagerSingleton();
}
});
}
private #Named("first") Bar first;
private #Named("second") Bar second;
static #Value class Foo { String name; }
static interface Bar {}
static class BarImpl implements Bar {
#Inject #Named Foo foo;
}
}
I'm trying to get a Bar object for both named Foos injected in my application. Basically, it should somehow connect the #Named on Foo with the one on Bar. I have tried several solutions, from putting #Named on everything to writing a custom Provider. The latter didn't work because I don't have access to the value of the #Named annotation inside the provider. I think the solution is somewhere in the line bind(Bar.class).to(BarImpl.class);, telling it to remember the value of the #Named annotation.
My question is, is this possible at all, and if so, how?
It is using PrivateModules. Basically:
A private module's configuration information is hidden from its environment by default. Only bindings that are explicitly exposed will be available to other modules and to the users of the injector. For more explanation see this FAQ entry.
Here is how you'd use it:
protected void configure() {
install(new PrivateModule() {
#Override
protected void configure() {
// #bind makes bindings internal to this module unlike using AbstractModule
// this binding only applies to bindings inside this module
bind(Foo.class).toInstance(new Foo("first"));
// Bar's foo dependency will use the preceding binding
bind(Bar.class).annotatedWith(Names.named("first")).to(BarImpl.class);
// if we'd stop here, this would be useless
// but the key method here is #expose
// it makes a binding visible outside as if we did AbstractModule#bind
// but the binding that is exposed can use "private" bindings
// in addition to the inherited bindings
expose(Bar.class).annotatedWith(Names.named("first"));
}
});
install(new PrivateModule() {
#Override
protected void configure() {
bind(Foo.class).toInstance(new Foo("second"));
bind(Bar.class).annotatedWith(Names.named("second")).to(BarImpl.class);
expose(Bar.class).annotatedWith(Names.named("second"));
}
});
bind(MyApplication.class).asEagerSingleton();
}
}
Now you effectively have 2 Bars each of which look like
static class BarImpl implements Bar {
#Inject Foo foo;
}
but with the power of PrivateModules have a different implementation bound for the same dependency.
Hope it makes sense.