Does GIN support anything like child injectors? - java

I have one application that contains sub-applications. I would like to segregate the GIN injection so that each sub-application can have separate instances of the same core shared classes. I also want the injector to supply classes from some core modules to all sub-applications, so that singleton instances can be shared. e.g.
GIN Modules:
Core - shared
MetadataCache - one per sub-application
UserProvider - one per sub-application
In Guice I can do this using createChildInjector, but I can't see an obvious equivalent in GIN.
Can I achieve something similar in GIN?

I solved this thanks to the link given by #Abderrazakk, but as the link isn't very forthcoming with instructions I thought I'd add a sample solution here too:
Private GIN modules allow you to have a single level of hierarchical injection, where types registered inside a private module are only visible to other instances created within that module. Types registered inside any non-private modules are still available to all.
Example
Let's have some sample types to inject (and inject into):
public class Thing {
private static int thingCount = 0;
private int index;
public Thing() {
index = thingCount++;
}
public int getIndex() {
return index;
}
}
public class SharedThing extends Thing {
}
public class ThingOwner1 {
private Thing thing;
private SharedThing shared;
#Inject
public ThingOwner1(Thing thing, SharedThing shared) {
this.thing = thing;
this.shared = shared;
}
#Override
public String toString() {
return "" + this.thing.getIndex() + ":" + this.shared.getIndex();
}
}
public class ThingOwner2 extends ThingOwner1 {
#Inject
public ThingOwner2(Thing thing, SharedThing shared) {
super(thing, shared);
}
}
Create two private modules like this (using ThingOwner2 for the second one):
public class MyPrivateModule1 extends PrivateGinModule {
#Override
protected void configure() {
bind(Thing.class).in(Singleton.class);
bind(ThingOwner1.class).in(Singleton.class);
}
}
And a shared module:
public class MySharedModule extends AbstractGinModule {
#Override
protected void configure() {
bind(SharedThing.class).in(Singleton.class);
}
}
Now register the two modules in our injector:
#GinModules({MyPrivateModule1.class, MyPrivateModule2.class, MySharedModule.class})
public interface MyGinjector extends Ginjector {
ThingOwner1 getOwner1();
ThingOwner2 getOwner2();
}
Finally we can look and see that both ThingOwner1 and ThingOwner2 instances have the same SharedThing instance from the shared module, but different Thing instances from their private registrations:
System.out.println(injector.getOwner1().toString());
System.out.println(injector.getOwner2().toString());

Here it is on SOF http://code.google.com/p/google-gin/wiki/PrivateModulesDesignDoc.
Hope it helps you out.

Related

Implementing a Singleton Builder in Dagger

I have a class that I would like to inject via Dagger. It requires a builder, as some of its parameters are only known at runtime. I would also like this class to be a singleton.
That is to say, several parts of our codebase require the instance of this class, but only one part of the codebase actually knows how to set it up.
The setup happens early on in the application - before anyone would actually try to use the singleton - but after Dagger has already initialized its root component.
What is the right way for other parts of the code to get access to the object?
class S {
private S(Foobar foobar) {
// ...
}
#Singleton
public static class Builder {
Foobar foobar;
#Inject
public Builder() {}
public Builder setFoobar(Foobar foobar) {
this.foobar = foobar;
}
public S build() {
return new S(foobar);
}
}
}
class Main {
private Foobar foobar = new Foobar();
private final S s;
#Inject
public Main(S.Builder sBuilder) {
s = sBuilder.setFoobar(foobar).build();
}
}
class Other {
private final S s;
#Inject
public Other(/* What do I put here to get access to S? */) {
}
Edit:
For clarity, let me state that Foobar in this example is created early in the application, but after Dagger and the high level structure of the app has been instantiated. This specific program is an Android app; the Foobar in this case a View that is inflated, and S a controller for that View.
There will only ever be one Foobar and one S. Various parts of our code want to be able to communicate with S, but only one part of our code can actually create it.
You can use BindsInstance for that https://dagger.dev/api/2.10/dagger/BindsInstance.html
Your Application creates the RootComponent. During creation it should provide the instance of the Foobar. Let's take a look at the pseudocode
class S {
private S(Foobar foobar) {
// ...
}
public static class Builder {
Foobar foobar;
public Builder() {}
public Builder setFoobar(Foobar foobar) {
this.foobar = foobar;
}
public S build() {
return new S(foobar);
}
}
}
#Module
public static class RootModule {
#Provides
#Singleton
public static S provideS(Foobar foobar) {
return new S.Builder().setFoobar(foobar).build();
}
}
#Singleton
#Component(module = {RootModule.class})
public interface RootComponent {
#Component.Factory
interface Factory {
public RootComponent create(#BindsInstance Foobar foobar)
}
}
public class Application {
private RootComponent createComponent() {
return DaggerRootComponent.factory().create(new Foobar())
}
}
Update
This specific program is an Android app; the Foobar in this case a View that is inflated, and S a controller for that View.
I strongly discourage you from keeping a reference to a View. This might produce subtle bugs and memory leaks. Instead I suggest you to introduce some sort of event bus which will be a singleton in your Dagger graph and shared between S (view controller) and consumers. This even bus will be used for communication between consumers and S (view controller).
Building off of a hint I gleamed from #MyDogTom's answer, introducing our first Subcomponent was the solution.
Wait to construct the S until after Foobar has been constructed. Then initialize a subcomponent, passing S to its Builder, and use the subcomponent to construct Other.
#Subcomponent
public interface MySubComponent {
#Subcomponent.Builder
interface Builder {
#BindsInstance Builder s(S s);
StatusBarComponent build();
}
/**
* Scope annotation for singleton items within the MySubComponent.
*/
#Documented
#Retention(RUNTIME)
#Scope
#interface MySubComponentScope {}
#MySubComponentScope
Ohter getOther();
}
// Attach MySubComponent to Dagger where appropriate, per their documentation.
// Then, in Main, do something like the following:
class Main {
private final MySubComponent.Builder mySubComponentBuilder;
private final S.Builder sBuilder;
private Foobar foobar;
#Inject
public Main(MySubComponent.Builder mySubComponentBuilder, S.Builder sBuilder) {
this.mySubComponentBuilder = mySubComponentBuilder;
this.sBuilder = sBuilder;
}
// At some point, foobar gets created. Then we call the following method.
private void afterInit();
S s = sBuilder.setFoobar(foobar).build();
Other other = mySubComponentBuilder.s(s).build().getOther();
}
}
This is a slightly contrived example, obviously, but demonstrates the solution to the problem.

Swappable modules with Dagger 2

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.

Guice won't intercept annotated methods

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

How to implement decorator pattern for Java class with protected methods

Subclass outside the package cannot access protected members on instances of parent class (only on instances of subclass itself or its subclasses).
JLS link: http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6.2
Here is an example. There is an existing class looking as the following:
package package1;
public abstract class BaseImplementation {
public String getResource1() {
return processTemplate1(getBaseUrl());
}
public String getResource2() {
return processTemplate2(getBaseUrl());
}
// Kind of 'Template Method' pattern.
protected abstract String getBaseUrl();
}
So intention is to write decorator like the following:
package package2;
public class ImplementationDecorator extends BaseImplementation {
private BaseImplementation delegate;
public ImplementationDecorator(BaseImplementation delegate) {
this.delegate = delegate;
}
#Override
protected String getBaseUrl() {
return trackServer + "?redirect=" + delegate.getBaseUrl();
}
}
The code will not compile.
getBaseUrl() has protected access in base class, and even subclasses cannot access that on parent instances.
So question is how to decorate such instances with protected methods without using 'dirty' tricks like reflection or putting subclass to package with the same name as parent class.
There are also examples of the same in Java language itself (e.g. javax.security.auth.login.ConfigurationSpi), and in cases I've found in Java - access from the same package is used.
What you're trying to do here is intercept behavior that's more or less private in the relationship between type BaseImplementation and one of its derived types—here, your "delegate" instance that you'd like to decorate in your ImplementationDecorator class. The author of BaseImplementation never anticipated someone wanting to get in the middle there, and the author of the type derived from BaseImplementation didn't anticipate that any callers other than BaseImplementation itself would get in there.
Instead, the pattern you're looking for would look more like this, which I'm afraid you can't retrofit if you don't own the classes involved:
public interface URLProvider
{
String getBase();
}
public final class BaseImplementation
{
public BaseImplementation(URLProvider provider)
{
if (null == provider)
throw new NullPointerException();
this.provider = provider;
}
public String getResource1()
{
return processTemplate1(provider.getBase());
}
public String getResource2()
{
return processTemplate2(provider.getBase());
}
private final URLProvider provider;
}
With that in place, if someone had written an implementation of type URLProvider, it would be easy to decorate, because now method URLProvider#getBase() is public.
Now, you may say, well, isn't that the same as just changing your BaseImplementation#getBaseUrl() method to be public, rather than protected? Not quite. Here, the design acknowledges—or even warns—that the URLProvider instance is a capability that can be used from anywhere.
This is not the good answer (I answered in a comment), but there's a way around:
public abstract class BaseImplementation {
(...)
protected String getBaseUrl(BaseImplementation other)
{
return other.getBaseUrl();
}
}
public class ImplementationDecorator extends BaseImplementation {
private BaseImplementation delegate;
(...)
#Override
protected String getBaseUrl() {
return trackServer + "?redirect=" + getBaseUrl(delegate);
}
}
Protected functions should be visible.. No need to use 'dirty tricks' to get access to them.
Here's what protected members are capable of:
Is available to all classes in the same package and also available to all subclasses of the class that owns the protected feature.This access is provided even to subclasses that reside in a different package from the class that owns the protected feature.

remove duplicate code in java

class A extends ApiClass
{
public void duplicateMethod()
{
}
}
class B extends AnotherApiClass
{
public void duplicateMethod()
{
}
}
I have two classes which extend different api classes. The two class has some duplicate
methods(same method repeated in both class) and how to remove this duplication?
Edit
Both ApiClass and AnotherApiClass are not under my control
Depending on what the code is you could do something like:
public class Util
{
public static void duplicateMethod()
{
// code goes here
}
}
and then just have the other two duplicateMethods call that one. So the code would not be duplicated, but the method name and the call to the Util.duplicateMethod would be.
If the code in the Util.duplicateMethod needed to access instance/class variables of the A and B class it wouldn't work out so nicely, but it could potentially be done (let me know if you need that).
EDIT (based on comment):
With instance variables it gets less pretty... but can be done. Something like:
interface X
{
int getVar();
void setVar(A a);
}
class A
extends ApiClass
implements X
{
}
class B
extends AnotherApiClass
implements X
{
}
class Util
{
public static void duplicateMethod(X x)
{
int val = x.getVal();
x.setVal(val + 1);
}
}
So, for each variable you need to access you would make a method for get (and set if needed). I don't like this way since it make the get/set methods public which may mean you are making things available that you don't want to be available. An alternative would be to do something with reflection, but I'd like that even less :-)
Sounds like a case for the "Strategy Pattern".
class A extends ApiClass {
private ClassContainingDupMethod strategy;
}
class N extends AnotherApiClass {
private ClassContainingDupMethod strategy;
public methodCallingDupMethod(){
strategy.dupMethod();
}
}
class ClassContainingDupMethod{
public dupMethod(){;}
}
Or is the dupMethod inherted from the Api classes?
Duplicate methods that rely on member variables imply duplicate member variables, too - and that starts to smell like too-large classes. What would those specific member variables, with the method(s), look like, if you were to extract them into their own class, and then compose that class into your other classes? Prefer composition over inheritance.
class BaseApiClass
{
public void duplicateMethod()
{
}
}
class ApiClass extends BaseApiClass
{
}
class AnotherApiClass extends BaseApiClass
{
}
class A extends ApiClass
{
}
class B extends AnotherApiClass
{
}
You need to combine the classes into one object and then all classes using th other two classes, modify their code to use the single class.

Categories