How to use Google Guice to inject a dependancy - java

I've gone through the user guide and everything but yet I still don't understand exactly how to modify existing code to use Google Guice when trying to inject dependencies. So to make it easier I created this simple example and if someone could explain with this simple example I would really appreciate it!
Say I have a
public Class A {
private int count = 0;
public A() {
}
public int getCount() {
return count;
}
public void setCount(int newCount) {
this.count = newCount;
}
}
and another class
public Class B {
private A objectA;
public B() {
objectA = new A();
}
public void messWithCount() {
int tempCount = objectA.getCount();
objectA.setCount(tempCount+1);
}
}
So basically my question is: how would I go about using Google Guice to extract creation of objectA in the constructor B() and instead inject it as a dependency in Class B where it would amount to something like
#Inject
public B() {
}
and how would I actually inject an instance of A into it?

First, B should not be bound to class A but rather use an interface (such as AInterface).
The main point of Guice is to bind different implementations of the same interface, without being tied to some class.
So let's assume Class A implements AInterface
interface AInterface {
public int getCount();
public void setCount(int newCount);
}
class A implements AInterface {
private int count = 0;
public A() {
System.out.println("done!");
}
#Override
public int getCount() {
return count;
}
#Override
public void setCount(int newCount) {
this.count = newCount;
}
}
Now you tell it to inject your variable:
class B {
#Inject
private AInterface objectA;
public B() {}
public void messWithCount() {
int tempCount = objectA.getCount();
objectA.setCount(tempCount + 1);
}
}
I removed the static modifier, but if you insist in having it static you'd need to bind using requestStaticInjection instead
you tie the implementation A to the interface AInterface in a special class called module:
class SimpleModule extends AbstractModule {
#Override
protected void configure() {
bind(AInterface.class).to(A.class);
}
}
Now you ask Guice to generate B for you.
public class Temptemp {
public static void main(String[] args) {
Injector i = Guice.createInjector(new SimpleModule());
B b = i.getInstance(B.class);
}
}

You can inject A into B in two ways, actually many ways but with in the context of your question I would say two.
Make sure both A and B class is configured in a Module. Follow condit example code/class that extends AbstractModule.
1.a
class B {
#Inject
private A a;
public B() {
}
}
1.b
class B {
private A a;
#Inject
public B(A a) {
this.a = a;
}
}
These both works fine but 1.b is useful if you want to write test for class B. Where your test will mock A class and creates instance of B. like
class BTest {
#Test
public void testSomeMethodOfB() {
A a = mock(A.class);
B b = new B(a);
//run some test on b;
}
}

Here's an example based on what you already have:
public class GuiceExample {
static class A {
private int count = 0;
public A() {}
public int getCount() {
return count;
}
public void setCount(int newCount) {
this.count = newCount;
}
}
static class B {
#Inject
private static A objectA;
public B() {}
public void messWithCount() {
int tempCount = objectA.getCount();
objectA.setCount(tempCount+1);
}
}
static class Module extends AbstractModule {
#Override
protected void configure() {
requestStaticInjection(B.class);
}
}
#Test
public void test() {
Injector i = Guice.createInjector(new Module());
B b = i.getInstance(B.class);
//Do something with b
}
}
Note, though, that static injection is not preferred. You could make A non static and Guice will still inject the field. The even more "correct" way would be to drop the requestStaticInjection call and add A as construction argument like:
static class B {
private A objectA;
#Inject
public B(A objectA) {
this.objectA = objectA;
}
...
}

Related

Java extends generic prototype

I have few classes that implements some interface. Now I want to create new class, which can extend one of them, based on runtime calculation while using interfaces methods. Let's talk in code:
public interface Interface {
public void doSomething();
}
public class A implements Interface {
#Override
public void doSomething() {
System.out.println("hello");
}
}
public class B implements Interface {
#Override
public void doSomething() {
System.out.println("hi");
}
}
These are existing classes, so now I need to do something like this (which is not working of course):
public class C<T extends Interface> extends T {
public void doSomethingElse() {
this.doSomething();
}
public static void main(String[] args) {
C c;
if(isSomethingLoaded) {
c = new C<A>();
} else {
c = new C<B>();
}
c.doSomethingElse();
}
}
Is it possible somehow, except the way that I pass argument Interface other to C's constructor and store to class property..?
A class cannot extend from its type parameter.
Use composition instead of inheritance:
public class C<T extends Interface> {
private final T foo;
public C(T foo){
this.foo = foo;
}
public void doSomethingElse() {
foo.doSomething();
}
public static void main(String[] args) {
C<?> c;
if(isSomethingLoaded) {
c = new C<>(new A());
} else {
c = new C<>(new B());
}
c.doSomethingElse();
}
}
You might even not need the type parameter here, but just use the interface type as argument/ member type.
I think it's situations like this which show why we have the rule of favouring composition over inheritance. Consider this solution using composition:
public class Test {
public interface Interface {
void doSomething();
}
public static class A implements Interface {
#Override
public void doSomething() {
System.out.println("Doing A");
}
}
public static class B implements Interface {
#Override
public void doSomething() {
System.out.println("Doing B");
}
}
public static class C implements Interface {
private Interface composedWith;
public C(Interface i) {
this.composedWith = i;
}
#Override
public void doSomething() {
this.composedWith.doSomething();
}
}
public static void main(String[] args) {
C c;
if(isSomethingLoaded) {
c = new C(new A());
} else {
c = new C(new B());
}
c.doSomething();
}
}
Personally, I feel this is a clearer and move flexible way of achieving what you are trying to do.

what scenario should abstract class used in java?

I am not familiar in OOPS concept, I have doubt while using abstract class, please clear my doubt.
I have four classes ex: class A, class B, class C and Main class.
class A, B and C contains same method name but the method definition is different
the implementation is like,
class A
{
getValue();
setValue();
}
class B
{
getValue();
setValue();
}
class C
{
getValue();
setValue();
}
In the Main class, I need to call setValue() or getValue(), it can be any of the above three class, how to implement this scenario?
class Main
{
Main()
{}
x.setValue();
x.getValue();
}
where x can be Object for either class A or class B or class C.
The abstract class defines, what methods are available. In your case, this would be
abstract class YourAbstractClass {
abstract public int getValue();
abstract public void setValue(int i);
}
Now your classes A, B and C can inherit this class.
class A extends YourAbstractClass {
public int getValue() { return 23; }
public void setValue(int i) { /* set i */ }
}
class B extends YourAbstractClass {
public int getValue() { return -3; }
public void setValue(int i) { /* set i */ }
}
class C extends YourAbstractClass {
public int getValue() { return 3; }
public void setValue(int i) { /* set i */ }
}
In your main class you can use it the like this:
public class Execution {
public static void main(String[] args) {
YourAbstractClass o = new A();
o.getValue();
o.setValue(3);
}
}
In your particular case you don't need an abstract class but an interface:
public interface I {
Object getValue();
Object setValue();
}
Then your 3 classes A, B and C must implement this interface:
class A implements I {
Object getValue() {...}
void setValue( someParam) {...}
}
class B implements I {
Object getValue() {...}
void setValue( someParam) {...}
}
class C implements I {
Object getValue() {...}
void setValue( someParam) {...}
}
And finally in your main class:
class Main
{
Main()
{
I x = callWhateverYouWantReturningABOrC();
x.setValue();
x.getValue();
}
You could implement that in a couple of ways:
public interface Valuable {
void getValue();
void setValue();
}
class A implements Valuable {
getValue() { ... }
setValue() { ... }
}
class B implements Valuable {
getValue() { ... }
setValue() { ... }
}
class C implements Valuable {
getValue() { ... }
setValue() { ... }
}
Or ...
abstract class Valuable {
void getValue() { ... }
void setValue() { ... }
}
class A extends Valuable {
}
class B extends Valuable {
}
class C extends Valuable {
}
Or ... a hybrid where you both interfaces and abstract classes.
Which is more appropriate depends on a number of things, including whether the method implementations are the same or not. If they are, then the abstract class eliminates some duplicate code.
If I got your question right, you want to create an interface:
interface I {
int getValue();
void setValue(int x);
}
and your classes will implement it:
class A implements I {..};
class B implements I {..};
class C implements I {..};
Then in your Main class you can have method, which doesn't have to know which concrete implementation of I the x variable is (wheather A, B or C) and it can call it's methods:
{
I x = new A(); // or new B() or C()
x.setValue(1);
x.getValue();
}
You can make Main an interface.
interface is a pure abstract class.
public interface Main {
void setValue();
void getValue();
}
Then make A, B, and C classes to implement the Main interface
public class A implements Main {
#Override
public void setValue() {
...
}
#Override
public void getValue() {
...
}
}
public class B implements Main {
#Override
public void setValue() {
...
}
#Override
public void getValue() {
...
}
}
public class C implements Main {
#Override
public void setValue() {
...
}
#Override
public void getValue() {
...
}
}

How to pass an object to a class that will be injected later

I am pretty new to google guice .
I am writing a nexus plugin where nexus injects some classes . for example say the class to be injected in class A.
Now before that class A is injected, I have another class B that was instantiated and inside it I have a method where an object (say obj) is initialised .
I have to pass this initialised object to the class A.
Normally if instantiation is under our control I will do as
A a = new A();
A.setObject(obj);
But now given that the class will be injected by the system , I don't know how to pass this initialised object to this class A.
If I understand correctly, you have something like
public class C {
}
public class A {
private C c;
public void setC(C c) {
this.c = c;
}
}
public class B {
private final C c;
public B() {
this.c = new C();
}
public C getC() {
return this.c;
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
A a = new A();
C c = b.getC();
a.setC(c);
}
}
This design does not follow DI principles and should be refactored. You should let Guice create your C instance. In that case you will have something like
public class C {
}
public class A {
private final C c;
#Inject
A(C c) {
this.c = c;
}
}
public class B {
private final C c;
#Inject
B(C c) {
this.c = c;
}
}
public class Main {
public static void main(String[] args) {
Injector injector = Guice.createInjector();
A a = injector.getInstance(A.class);
B b = injector.getInstance(B.class);
}
}
And here you have C automatically injected both into A and B.
If you really cannot refactor you code, consider using providers then:
public class AProvider extends Provider<A> {
private final B b;
#Inject
AProvider(B b) {
this.b = b;
}
#Override
public A get() {
A a = new A();
C c = b.getC();
a.setC(c);
// Or, better
// A a = new A(b.getC());
return a;
}
}
public class Main {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new AbstractModule() {
#Override
protected void configure() {
bind(A.class).toProvider(AProvider.class);
}
});
A a = injector.getInstance(A.class);
}
}
In this case a provider is used to create A and set its C dependency.
But sometimes even that is not enough (e.g. when your B.getC() behavior depends on user input). In that case you have to use assisted inject extension:
public interface AFactory {
public A create(C c);
}
public class A {
private final C c;
private final Other other;
#Inject
A(#Assisted C c, Other other) {
this.c = c;
this.other = other;
}
}
public class Main {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new AbstractModule() {
#Inject
protected void configure() {
install(new FactoryModuleBuilder()
.build(AFactory.class));
}
});
B b = injector.getInstance(B.class);
C c = b.getC(someUserInput);
AFactory af = injector.getInstance(AFactory.class);
A a = af.create(c);
}
}
In the last example two object will be injected into A via af.create(c) invocation: first, that c you have provided, and second, and instance of Other class which is resolved automatically by Guice. In other words, assisted inject allows you to instantiate classes which will have one part of their dependencies resolved by you, and other part - by Guice.

Force the execution of a method in a class

I'm using Java and I want to call the method f2 in class A from the class B. Is it possible to do this?
public class A{
private B b = new B();
public void f1(){
b.f3();
}
public void f2(){
// do something;
}
}
public class B{
public void f3(){
// Call f2 of class A from here.
}
}
You need an instance of A in class B and invoke f2 on that instance. For example, you could instantiate one inside the body of f3:
public class B {
public void f3() {
A a = new A();
a.f2();
}
}
Another way would be for f3 to receive an instance of A:
public class B {
public void f3(A a) {
a.f2();
}
}
And yet another way, you could have B instantiate one:
public class B {
private final A a;
public B() { this.a = new A(); }
public void f3() {
this.a.f2();
}
}
And lastly, B could receive one in it's constructor:
public class B {
private final A a;
public B(A a) { this.a = a; }
public void f3() {
this.a.f2();
}
}
The point being that if you want to invoke an instance method on a class you must have an instance of that class in your hand.
Finally, I notice that you have A.f1 invoking B.f3 and from there you want to invoke A.f2. So, it looks like your best option here is the second option above. That is:
public class A {
private final B = new B();
public void f1() { this.b.f3(this); }
public void f2() { /* do something */ }
}
public class B {
public void f3(A a) { a.f2(); }
}
The key here is that we are passing an instance of A to B.f3. The way that we achieve that is by passing the this reference, which is a reference to the currently executing instance. In A.f1, that would be the instance of A that is currently executing.
You need an instance of class A to do this.
public class A{
private B b = new B();
public void f1(){
b.f3(this);
}
public void f2(){
// do smthing;
}
}
public class B{
public void f3(A a){
a.f2(); // Call f2 of class A from here.
}
}
This type of code structure is usually more confusing than useful. I suggest instead doing this.
public class A{
private B b = new B();
public void f1(){
WhatAf2Needs w = b.f3();
f2(w);
}
public void f2(WhatAf2Needs w){
// do smthing;
}
}
public class B{
public WhatAf2Needs f3(A a){
return WhatAf2Needs;
}
}
If you want to call a method of the thing that called you, you have to have the caller pass itself in using the this keyword. In code, it would be:
public class A{
private B b = new B();
public void f1(){
b.f3(this);
}
public void f2(){
// do smthing;
}
}
public class B{
public void f3(A caller){
caller.f2();
}
}
You would have to instantiate class A in class B, given the way it's currently written, to make any method calls on it.
You can also declare f2 static and call it like A.f2(). This type of things depend a lot on the design of your classes though. The other answers here are very valid too.
public class A{
private B b = new B();
public void f1(){
b.f3();
}
public static void f2(){
// do smthing;
}
}
public class B{
public void f3(){
A.f2();
}
}

How to override/extend an inner class from a subclass?

I want to change how a method of a class executes without overriding the method, and only overriding (or ideally extending) the inner class. Assume that I cannot change the fact that I need to do this (I am modifying an existing open source code base and there would be friction to pulling out classes or whatnot).
public class A {
static class Thing {
public int value() { return 10+value2(); }
public int value2() { return 10; }
}
public String toString() {
Thing t = new Thing();
return Integer.toString(t.value());
}
}
public class B extends A {
static class Thing {
public int value2() { return 20; }
}
}
My goal is, by changing only Thing, getting B's toString() to return "30", where currently it will return "20". The ideal would be to change only the method value2 (thus leaving any other methods unchanged), but I don't know if this is possible.
Thanks
I think you need a factory method for this. Consider the following example (derived from your snippet):
static class A {
static class Thing {
public int value() {
return 10 + value2();
}
public int value2() {
return 10;
}
}
protected Thing createThing() {
return new Thing();
}
public String toString() {
return Integer.toString(createThing().value());
}
}
static class B extends A {
static class Thing extends A.Thing {
public int value2() {
return 20;
}
}
#Override
protected Thing createThing() {
return new Thing(); // creates B.Thing
}
}
public static void main(String[] args) {
System.out.println(new B());
}
Output:
30
You should be able to just extend the inner class with Thing extends A.Thing. As long as it's visible in your scope it shouldn't be a problem.
It's not possible by only changing value2. The problem is that 'new' calls aren't dispatched dynamically - the 'new' in toString will always create A::Thing. You could fix this creating a factory : something like this:
public class A {
static class Thing {
public int value() { return 10+value2(); }
public int value2() { return 10; }
}
private Thing makeThing() { return new Thing(); }
public String toString() {
Thing t = new Thing();
return Integer.toString(t.value());
}
}
public class B extends A {
static class Thing extends A.Thing {
public int value2() { return 20; }
}
private Thing makeThing() { return new Thing(); }
}

Categories