Suppose I have a value for which I have a default, which can be overridden if System.getProperty("foo") is set. I have one module for which I have
bindConstant().annotatedWith(Names.named("Default foo")).to(defaultValue);
I'm wondering what the best way of implementing a module for which I want to bind something annotated with "foo" to System.getProperty("foo"), or, if it does not exist, the "Default foo" binding.
I've thought of a simple module like so:
public class SimpleIfBlockModule extends AbstractModule {
#Override
public void configure() {
requireBinding(Key.get(String.class, Names.named("Default foo")));
if (System.getProperties().containsKey("foo")) {
bindConstant().annotatedWith(Names.named("foo")).to(System.getProperty("foo"));
} else {
bind(String.class).annotatedWith(Names.named("foo")).to(Key.get(String.class, Names.named("Default foo")));
}
}
}
I've also considered creating a "system property module" like so:
public class SystemPropertyModule extends PrivateModule {
#Override
public void configure() {
Names.bindProperties(binder(), System.getProperties());
if (System.getProperties().contains("foo")) {
expose(String.class).annotatedWith(Names.named("foo"));
}
}
}
And using SystemPropertyModule to create an injector that a third module, which does the binding of "foo". Both of these seem to have their downsides, so I'm wondering if there is anything I should be doing differently. I was hoping for something that's both injector-free and reasonably generalizable to multiple "foo" attributes. Any ideas?
Your first design seems like the best option to me if you don't need the binding to change at runtime (i.e. the binding is constant as of injector creation time).
For any value you decide at runtime, you'll need a Provider or a #Provides method:
public class SimpleIfBlockModule extends AbstractModule {
#Override public void configure() { }
#Provides #Named("foo") String provideFoo(
#Named("Default foo") String defaultFoo,
AnyInjectableDependencyHere ifNeeded) {
if (System.getProperties().containsKey("foo")) {
return System.getProperty("foo");
} else {
return defaultFoo;
}
}
}
If you need to decide at runtime based on a parameter, use this solution.
Related
I want to create a common service and common request as shown below:
public interface CommonService {
CommandDTO createOrUpdate(CommonRequest request);
}
Then implement this service as shown below:
public class CompanyARequest extends CommonRequest {
// properties
}
public class CompanyAServiceImpl implements CommonService {
#Override
public CommandDTO createOrUpdate(CompanyARequest request) {
// ...
}
}
However, although CompanyARequest is inherited from CommonRequest, createOrUpdate method throws "Method does not override method from its superclass" error.
On the other hand, if I use generic for the request, the error is gone, but if I use generic for request and dto, there will be too much letter is used and I just want to use generic letters for entities that will be used in CommonService. SO, how can I fix this problem? Is there any mistake of my implementation?
You are looking for a generic interface from what I understand:
public interface CommonService<C extends CommonRequest> {
CommandDTO createOrUpdate(C request);
}
public class CompanyAServiceImpl implements CommonService<CompanyARequest> {
#Override
public CommandDTO createOrUpdate(CompanyARequest request) {
// ...
}
}
If you were to define it like you first did, the issue is that any CommonRequest should be accepted by the method according to its definition in the interface.
The CompanyAServiceImpl::createOrUpdate implementation only contemplates a small subset of the entire space defined by CommonService::createOrUpdate. That is why it is stated that "method does not override method from its superclass" (not entirely, at least).
To see it, think of a certain method that receives as parameter any CommonService, for example:
void runService(CommonService commonService) { ... }
How can runService know (at compile time) what is the correct parameter for commonService.createOrUpdate? It only knows that it must be CommonRequest (or, transitively, any class that extends it). But your CompanyAServiceImpl::createOrUpdate implementation only supports one of them.
In other words, createOrUpdate must support any parameter that is a CommonRequest.
The best you can do depends on the type of abstraction you are looking for (and your question does not describe the problem to be solved).
However, you might be looking for something similar to:
interface CommonRequest {
String requestDescription();
}
interface CommonService<Request extends CommonRequest> {
String serviceName();
boolean createOrUpdate(Request request);
}
static class CompanyARequest implements CommonRequest {
public String requestDescription() { return "A Req"; }
}
static class CompanyAService implements CommonService<CompanyARequest> {
public String serviceName() { return "A Co"; }
public boolean createOrUpdate(CompanyARequest companyARequest) { return true; }
}
static class CompanyBRequest implements CommonRequest {
public String requestDescription() { return "B Req"; }
}
static class CompanyBService implements CommonService<CompanyBRequest> {
public String serviceName() { return "B Co"; }
public boolean createOrUpdate(CompanyBRequest companyBRequest) { return false; }
}
Now, all processes calling createOrUpdate will be forced to know which parameter is the correct one, but common processes for all companies can still share a single implementation, for example running with logging:
static <R extends CommonRequest> void runService(CommonService<R> service, R request) {
System.out.printf("Running service '%s':%n", service.serviceName());
if(service.createOrUpdate(request))
System.out.printf(" - Success with parameter '%s'.%n", request.requestDescription());
else
System.out.printf(" ! Error with parameter '%s'.%n", request.requestDescription());
}
if we run
runService(new CompanyAService(), new CompanyARequest());
runService(new CompanyBService(), new CompanyBRequest());
we get
Running service 'A Co':
- Success with parameter 'A Req'.
Running service 'B Co':
! Error with parameter 'B Req'.
Of course, all this is if that parameter (CommonRequest) and that method (createOrUpdate) are going to be used generically in many places in your application, otherwise, just add a new method to your company:
public class CompanyAServiceImpl implements CommonService {
#Override
public CommandDTO createOrUpdate(CompanyRequest request) {
// ...
}
public CommandDTO createOrUpdateWithA(CompanyARequest request) {
// ...
}
}
Let's say I have a ThirPartyModule third-party Module which binds lots of components that I can then use in my application :
Injector guice = Guice.createInjector(new MyAppModule(), new ThirPartyModule());
If I want to modify the implementation classes used for some bindings in that Module, what is the best approach?
For example, let's say ThirPartyModule performs that binding :
bind(WidgetInterface.class).to(DefaultWidgeImpl.class).in(Scopes.SINGLETON);
and I want to be able to change the DefaultWidgeImpl class for MyWidgetImpl class. I know I could use an overriding Module, and simply rebind the WidgetInterface key. But what if ThirPartyModule binds a lot of things using that same Widget implementation? I may not want to have to rebind each of them!
So I'm trying to find the best solution to be able to specify the implementation class to use, without having the rebind all the components depending on it.
I guess ThirPartyModule could first create a getter method for the implementation class :
bind(WidgetInterface.class).to(getWidgetImpClass()).in(Scopes.SINGLETON);
protected Class<? extends WidgetInterface> getWidgetImpClass() {
return DefaultWidgeImpl.class;
}
and then the application could override the getWidgetImpClass() method :
Injector guice = Guice.createInjector(new MyAppModule(), new ThirPartyModule() {
#Override
protected Class<? extends WidgetInterface> getWidgetImpClass() {
return MyWidgetImpl.class;
}
});
I also though about passing the implementation class to the constructor of the Module :
Injector guice = Guice.createInjector(new MyAppModule(), new ThirPartyModule(MyWidgetImpl.class));
I'd like to know if there is an accepted pattern to customize such third-party Modules? Let's say I can ask the Modules to be written in a specific way if it helps them to be customizable.
Here's how I would do it:
public class ThirdPartyModule extends AbstractModule {
#Override
protected void configure() {
// CoolWidget --
// \
// > WidgetInterface -> DefaultWidgetImpl
// /
// AwesomeWidget
OptionalBinder.newOptionalBinder(binder(), WidgetInterface.class)
.setDefault()
.to(DefaultWidgetImpl.class);
bind(CoolWidget.class).to(WidgetInterface.class);
bind(AwesomeWidget.class).to(WidgetInterface.class);
// etc.
}
}
public class MyAppModule extends AbstractModule {
#Override
protected void configure() {
OptionalBinder.newOptionalBinder(binder(), WidgetInterface.class)
.setBinding()
.to(CustomWidgetImpl.class);
}
}
By making all the bindings go indirectly through the WidgetInterface key, you only need to override that one binding.
So I have some code that runs an algorithm, say with an AlgoRunner class. Now this AlgoRunner class can be implemented in multiple ways to run different algorithms using Algo classes. I want to use Dagger 2 to provide different implementations of the AlgoRunner class to a "Manager" class that passes input to AlgoRunner as well as other components that it manages.
Question
I have the following right now, but I'm not sure if this is the correct way, mainly because of that empty AlgoRunnerProvider module. Is that any other way to achieve what I'm trying to do? Or to simplify what I have?
Should I just create different components, OneAlgoRunnerComponent and TwoAlgoRunnerComponent and inject the Manager from each of those?
The class that constructs the Manager instance uses this component to inject the AlgoRunner into that instance so that the Manager can pass it the inputs.
#Component(
modules = {
AlgoRunnerProvider.class
}
)
public interface AlgoRunnerComponent {
void inject(Manager manager);
AlgoRunner getAlgoRunner();
}
AlgoRunnerProvider Module
#Module
public class AlgoRunnerProvider {
#Provides
public AlgoRunner getAlgoRunner() {
return null;
}
}
OneAlgoRunnerProvider, that overrides the provides method in AlgoRunnerProvider.
Could have a TwoAlgoRunnerProvider as well, that does the same thing and provides TwoAlgoRunner, as long as that extends AlgoRunner.
public class OneAlgoRunnerProvider extends AlgoRunnerProvider {
private final OneAlgo algo;
public OneAlgoRunnerProvider(OneAlgo algo) {
this.algo = algo;
}
#Override
public OneAlgoRunner getAlgoRunner() {
return new OneAlgoRunner(algo);
}
}
All this is used like this right now:
AlgoRunnerComponent build = DaggerAlgoRunnerComponent.builder()
.algoRunnerProvider(new OneAlgoRunnerProvider(new OneAlgo()))
// .algoRunnerProvider(new TwoAlgoRunnerProvider(new TwoAlgo()))
.build();
Manager manager = managerComponent.getManager();
build.inject(manager);
Truth.assertThat(manager.algoRunner).isInstanceOf(OneAlgoRunner.class);
// Truth.assertThat(manager.algoRunner).isInstanceOf(OneAlgoRunner.class);
Thanks a lot!
The dagger framework is used to handle object creation for you. If you start doing some sort of initialization in one of your classes you wish to provide, there is probably something not as it is supposed to be (see getAlgoRunner()).
If you have different types that you want to provide at runtime, you want a factory of some sorts to create the correct object. Enter dagger.
You have multiple ways of achieving what you want. Basically, the module should handle the object creation:
#Module
public class AlgoRunnerProvider {
#Provides
public AlgoRunner getAlgoRunner() {
// todo create the correct type
return null;
}
}
1. #Named annotation (or some other Qualifier)
If you know at compile time which class is going to need which type, you should use qualifiers.
#Named("Version1")
#Inject
AlgoRunner mRunner;
You then just can provide different implementations from your module:
#Provides
#Named("Version1")
public AlgoRunner getAlgoRunner() {
return new Version1AlgoRunner();
}
#Provides
#Named("OtherVersion")
public AlgoRunner getAlgoRunner(Depends someOtherDependency) {
return new OtherVersionAlgoRunner(someOtherDependency);
}
2. Switching at runtime
While you could always use the first option by creating multiple classes with different dependencies, you might want to be able to chose at runtime. For this, you need to pass in some argument to your module:
#Module
public class AlgoRunnerProvider {
private final int mType;
public AlgoRunnerProvider(int type) {
mType = type;
}
#Provides
public AlgoRunner getAlgoRunner() {
if(mType == TYPE_A) {
return new Version1AlgoRunner();
} else {
return new OtherVersionAlgoRunner();
}
}
}
With this variant you still have your creation logic inside your module, where your dependencies come from.
3. Use different modules
Another approach would be to use different modules. This will only be a clean solution if determined at compile time (different classes using different modules) and not some choosing logic at runtime in the same class.
If you start writing code like if typeA then moduleA else moduleB you should probably stop and do something else.
You can use the same component but create it using different modules for different classes by using good old inheritance. Every module just provides its implementation of AlgoRunner.
// one class using one module to get a specific behavior
public class MyClassVersionA {
public void onCreate(Bundle saved) {
component.myModule(new MyModuleVersionA()).build();
}
}
// another class using a different module to get a different behavior
public class MyClassSomethingElse {
public void onCreate(Bundle saved) {
component.myModule(new MyModuleSomethingElse()).build();
}
}
You would then just subclass your module accordingly like so
// did not test the following, something like this...
public abstract class MyModule {
#Provides
public AlgoRunner getAlgoRunner();
}
public class MyModuleVersionA extends MyModule {
#Provides
#Override
public AlgoRunner getAlgoRunner() {
return new Version1AlgoRunner();
}
}
public class MyModuleSomethingElse extends MyModule {
#Provides
#Override
public AlgoRunner getAlgoRunner() {
return new SomeOtherAlgoRunner();
}
}
There are probably even more possibilities, especially if starting to mix those approaches, but I think those 3 to be the basic tools that you can use.
Is it possible to instantiate and assign a singleton to a reference with Guice before creating the Module and pass that instance to the Module constructor be bound during configuration?
Here is an example of what I mean:
I have a method that allows me to create objects depending on a custom implementation of an interface which is being passed in constructor as an Optional (if the user won't provide a custom implementation, we will use the default one), which is being done by binding the interface to that particular implementation in the Module class. :
public static MyClass createMyClassObject(Optional<SpecialInterface> customSpecialInterfaceObject) {
SpecialInterface specialInterfacebject;
if(customSpecialInterfaceObject.isPresent() {
specialInterfaceObject = customSpecialInterfaceObject.get()
} else {
/* here I would like to bind it to an instance of the DefaultSpecialInterfaceObject but can't really do something like:
Injector injector = Guice.createInjector(myClassModule);
DefaultSpecialInterface instance = injector.getInstance(DefaultSpecialInterface.class);
as the module is yet to be created */
}
MyClassModule myClassModule = new MyClassModule(specialInterfaceObject);
Injector injector = Guice.createInjector(myClassModule);
return injector.getInstance(MyClass.class);
}
I'm currently using classes instead of instances to solve this problem, such as in the example below, but I don't quite like this solution. Would be happy to see a better way of doing it:
private static Class resolveSpecialInterfaceObject(Optional<SpecialInterface> customSpecialInterfaceObject) {
Class specialInterfaceObjectClass;
if (customSpecialInterfaceObject.isPresent()) {
specialInterfaceObjectClass= customSpecialInterfaceObject.get().getClass();
} else {
specialInterfaceObjectClass = DefaultSpecialInterface.class;
}
return specialInterfaceObjectClass;
}
public abstract class MyClassModule extends AbstractModule {
private final Class<SpecialInterface> specialInterfaceObjectClass;
public MyClassModule(Class<SpecialInterface> specialInterfaceObjectClass) {
this.specialInterfaceObjectClass= specialIntefaceObjectClass;
}
#Override
protected void configure() {
bind(SpecialInterface.class).to(specialInterfaceObjectClass);
}
}
Edit, from a comment below:
one more thing- didn't want to make the question too long; actually, I also want to perform another operation on the resulting instance of SpecialInterface, but only if it is the instance of DefaultSpecialInterface and I don't think it should be done in the Module. I was thinking if I could just have this bean up and running before, such as in Spring, so I could just pass it to the Module, but also use it in another method call before?
Can you take the whole Optional and use bind(...).toInstance(...)?
public static MyClass createMyClassObject(
Optional<SpecialInterface> customSpecialInterfaceObject) {
MyClassModule myClassModule = new MyClassModule(customSpecialInterfaceObject);
Injector injector = Guice.createInjector(myClassModule);
MyClassFactory instance = injector.getInstance(MyClassFactory.class);
return instance.createMyClassObject();
}
class MyClassModule extends AbstractModule {
private final Optional<SpecialInterface> customObject;
MyClassModule(Optional<SpecialInterface> customObject) {
this.customObject = customObject;
}
#Override public void configure() {
if (customObject.isPresent()) {
// Singleton by necessity: Guice doesn't know how to create another one.
bind(SpecialInterface.class).toInstance(customObject.get());
} else {
// Default scoped. Add ".in(Singleton.class)" if necessary.
bind(SpecialInterface.class).toInstance(DefaultSpecialInterfaceClass.class);
}
}
}
If you want to perform additional initialization on DefaultSpecialInterface and nothing else, you have a number of options:
If some kind of initialization is important for all implementations and likely too heavy to put into a class constructor, add an initialize method on your SpecialInterface. Make the custom one a no-op, and implement it for DefaultSpecialInterface.
If the initialization is unique to DefaultSpecialInterface, I see no reason why it shouldn't be in the Module. Write a #Provides method or bind to a Provider<SpecialInterface> that creates and initializes DefaultSpecialInterface correctly.
If your real goal is to keep the business logic out of a Module, you can do so by extracting it into a free-standing Provider or DefaultSpecialInterfaceFactory that is responsible for that.
Remember, Guice is responsible for feeding fully-constructed objects into your object graph, and that means that injecting a SpecialInterface should get a ready-to-use implementor of the SpecialInterface general contract. If Guice needs to perform some initialization to make that happen, it's not unreasonable to have it do so, and a Module isn't a bad place to do it.
I have a situation where Guice is working for some bindings, and not at all for others. Clearly I am using the API incorrectly.
In part, it's probably because I'm trying to get too "fancy" with how I'm using Guice. I've created an inheritance tree of Modules and I think I've gotten too clever (or foolish!) for my own good.
Before you look at the code below, just please understand my intention, which was to provide a reusable Module that I can place in a JAR and share across multiple projects. This abstract, reusable Module would provide so-called "default bindings" that any implementing Module would automatically honor. Things like an AOP MethodInterceptor called Profiler, which looks for methods annotated with #Calibrated and automatically logs how long it took for that method to execute, etc.
Observe the following:
#Target({ ElementType.METHOD })
#RetentionPolicy(RetentionPolicy.RUNTIME)
#BindingAnnotation
public #interface Calibrated{}
public class Profiler implement MethodInterceptor {
#Override
public Object invoke(MethodInvocation arg0) throws Throwable {
// Eventually it will calculate and log the amount of time
// it takes an intercepted method to execute, hence "Profiler".
System.out.println("Intercepted!");
return arg0.proceed();
}
}
public abstract class BaseModule implements Module {
private Binder binder;
public BaseModule() {
super();
}
public abstract void bindDependencies();
#Override
public void configure(Binder bind) {
// Save the binder Guice passes so our subclasses can reuse it.
setBinder(bind);
// TODO: For now do nothing, down the road add some
// "default bindings" here.
// Now let subclasses define their own bindings.
bindDependencies();
}
// getter and setter for "binder" field
// ...
}
public abstract class AbstractAppModule extends BaseModule {
/* Guice Injector. */
private Injector injector;
// Some other fields (unimportant for this code snippet)
public AbstractAppModule() {
super();
}
// getters and setters for all fields
// ...
public Object inject(Class<?> classKey) {
if(injector == null)
injector = Guice.createInjector(this);
return injector.getInstance(classKey);
}
}
So, to use this small library:
public class DummyObj {
private int nonsenseInteger = -1;
// getter & setter for nonsenseInteger
#Calibrated
public void shouldBeIntercepted() {
System.out.println("I have been intercepted.");
}
}
public class MyAppModule extends AbstractAppModule {
private Profiler profiler;
// getter and setter for profiler
#Override
public void bindDependencies() {
DummyObj dummy = new DummyObj();
dummy.setNonsenseInteger(29);
// When asked for a DummyObj.class, return this instance.
getBinder().bind(DummyObj.class).toInstance(dummy);
// When a method is #Calibrated, intercept it with the given profiler.
getBinder().bindInterceptor(Matchers.any(),
Matchers.annotatedWith(Calibrated.class),
profiler);
}
}
public class TestGuice {
public static void main(String[] args) {
Profiler profiler = new Profiler();
MyAppModule mod = new MyAppModule();
mod.setProfiler(profiler);
// Should return the bounded instance.
DummyObj dummy = (DummyObj.class)mod.inject(DummyObj.class);
// Should be intercepted...
dummy.shouldBeIntercepted();
System.out.println(dummy.getNonsenseInteger());
}
}
This is a lot of code so I may have introduced a few typos when keying it all in, but I assure you this code compiles and throws no exceptions when ran.
Here's what happens:
The #Calibrated shouldBeIntercepted() method is not intercepted; but...
The console output shows the dummy's nonsense integer as...29!!!!
So, regardless of how poor a design you may think this is, you can't argue that Guice is indeed working for 1 binding (the instance binding), but not the AOP method interception.
If the instance binding wasn't working, then I would happily revisit my design. But something else is going on here. I'm wondering if my inheritance tree is throwing the Binder off somehow?
And I've verified that I am binding the interceptor to the annotation correctly: I created another package where I just implement Module (instead of this inheritance tree) and use the same annotation, the same Profiler, and it works perfectly fine.
I've used Injector.getAllBindings() to print out the map of all my MyAppModule's bindings as Strings. Nothing is cropping up as the clear source of this bug.
Interception only works on Objects created by Guice (see "Limitations" http://code.google.com/p/google-guice/wiki/AOP#Limitations). You are using "new" to create the DummyObj, so no matter how clever your Module is Set up, the instance is created Outside guice.
Here's a little snipplet based on your coding. (I use your Calibrated Annotation, but had everything else in one class. You should have a look at "AbstractModule". It saves a lot of manual stuff you did with your Module-Hierarchy.
public class MyModule extends AbstractModule implements MethodInterceptor {
#Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("Intercepted#invoke!");
return methodInvocation.proceed();
}
#Override
protected void configure() {
bind(Integer.class).annotatedWith(Names.named("nonsense")).toInstance(29);
bindInterceptor(Matchers.any(), Matchers.annotatedWith(Calibrated.class), this);
}
public static void main(String... args) {
Dummy dummy = Guice.createInjector(new MyModule()).getInstance(Dummy.class);
dummy.doSomething();
System.out.println(dummy.getNonsense());
}
}
And my Dummy:
public class Dummy {
#Inject
#Named("nonsense")
private int nonsense;
public int getNonsense() {
return nonsense;
}
public void setNonsense(int nonsense) {
this.nonsense = nonsense;
}
#Calibrated
public void doSomething() {
System.out.println("I have been intercepted!");
}
}
So you see? I never use the word "new" (except for the Module ....). I let Guice handle the Dummy-Object and just configure the value for the nonsense int, which is then injected.
Output:
Intercepted#invoke!
I have been intercepted!
29