Guice example on how to correctly wire objects - java

I am trying to learn Guice and I have a question on how to correctly wire up things. I am trying to get the call in BoofPanels doSomething() method to automatically use the MockFooImpl, but I don't think things are wired properly.
In my case I have:
#ImplementedBy(MockFooImpl.class)
public interface FooInterface {
public int getBar(String one, String two);
}
#Singleton
public final class MockFooImpl implements FooInterface {
#Inject
public MockFooImpl() {
}
#Override
public int getBar(String one, String two) {
return 1;
}
}
public class Baz extends JFrame {
private BoofPanel boofPanel;
public Baz(String one, String two, Injector injector){
// Constructor with args
boofPanel = new BoofPanel("aString", 565);
injector.injectMembers(boofPanel);
}
public static void main(String[] args){
final Injector injector = Guice.createInjector();
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
final Baz baz = new Baz("one","two", injector);
baz.setVisible(true);
}
});
}
}
public class BoofPanel extends JPanel {
#Inject
private FooInterface fooI;
public BoofPanel(String aString, int anInt){
}
public void doSomething(){
fooI.getBar();
}
}
Any help would be appreciated.
Thanks!

Guice isn't magic. It will only inject into an object if either it creates it, or you ask it to. If you're creating your own BoofPanel, then you'll need to ask Guice to inject it. Add a constructor to Baz that looks like:
public Baz(Injector injector) {
boofPanel = new BoofPanel(whatever, the, params, are);
injector.injectMembers(boofPanel);
}
The BoofPanel constructor doesn't need to do anything to the fooI variable; it can leave it null. You'll also need to make main's injector variable final, so the anonymous class created in main can capture it and pass it into the Baz constructor.
If you'd rather have BoofPanel created by Guice, then you'll need to supply all the constructor parameters it needs to Guice, and call injectMembers on Baz itself.
EDIT: Specific changes to the code above, after edits.
Add a final to this declaration, to make it usable inside the anonymous inner class:
final Injector injector = Guice.createInjector();
Remove this line, as it's unnecessary:
injector.getInstance(MockFooImpl.class);
Add the injector to the invocation of the Baz constructor, to get it to where BoofPanel is created (i've also removed the unnecessary final here):
Baz baz = new Baz("one", "two", injector);
Add the injector to the declaration of the Baz constructor, to receive it from the main method:
public Baz(String one, String two, Injector injector) {
Add an injection into boofPanel to the Baz constructor, right after the new BoofPanel line, to get Guice to inject BoofPanel:
injector.injectMembers(boofPanel);
That's it.

You probably want
public class BoofPanel extends JPanel {
private FooInterface fooI;
#Inject BoofPanel(FooInterface foo) {
this.fooI = foo;
}
public void doSomething() {
fooI.getBar();
}
}
and then in your main you probably want something like injector.createInstance(BoofPanel.class) and it'll automatically fulfill the FooInterface requirement with a MockFooImpl.

Related

How to nest methods in java to force user to use the nested name?

I'm writing a library, for more readability I want to force user to use nested methods to call the correct functions.
For example this is my class looks like:
public class Foo{
public void methodA(){}
public void methodB(){}
public void methodC(){}
}
What I'm expecting the user:
Foo foo = new Foo();
foo.methodA.methodB();
foo.methodA.methodC();
to call method B & C through calling the methodA as a prefix
After reading your question i think you are asking about Builder Design patten in which every methods return type is same class object and you can make call hierarchy like this.
obj.aMethod().bMethod().cMethod();
in your example just do like this:
public class Foo{
private static final Foo instance = new Foo();
private Foo(){}
public static Foo getInstance(){
return instance;
}
public Foo methodA(){
//Do stuff
return getInstance();
}
public Foo methodB(){}
public Foo methodC(){}
}
Now you can call like objfoo.getInstance().methodA().methodB();
Hope it will help you. To read more about that pattern
To force the user to use methodA to access methodB you could use an inner class.
In methodB you can access the Foo-Object with Foo.this.
public class Foo{
public Bar methodA()
{
// ...
return new Bar();
}
public class Bar {
private Bar() {}; // only methodA can create a Bar object
public void methodB(){}
public void methodC(){}
}
}
This is called as method chaining. You will need to set the return type of all methods as the same as the Class.
public class Foo{
public Foo methodA()
public Foo methodB()
public Foo methodC()
}
Now the client can simply call:
foo.methodA().methodB(), etc.
You can have one "terminal method" i.e. one that does not return a value. For example
public void methodD();
This method will be called last.
foo.methodA().methodB().methodC().method();
This line in itself will be valid as return type is void.
Please look at method chaining/ builder pattern YouTube videos, it will be clear.

Does method injection with Guice work if constructor is not injected?

I have a class where I need to inject a variable but the constructor is not guice injected.
public class Foo{
private boolean x;
public Foo(){
//sets some variables
}
#Inject
public void setX(boolean x){
this.x=x;
}
}
The value of x is not getting injected. Is it necessary to use injection in constructor for guice to recognize method injection?
Do I need to call this method from some other class for this to work?
Thanx in advance
If you're going to use Guice to #Inject Foo then Guice needs to create the object - either from the injector or from another #Inject point in separate class. Guice can't help you inject objects that it didn't create.
In this case it's not necessary to add #Inject to the constructor because Guice can automatically inject a no argument constructor. For example:
public class MethodInjectionTest {
static class Foo {
private boolean x;
public Foo(){
//sets some variables
}
#Inject
public void setX(boolean x){
this.x=x;
}
}
Injector i = Guice.createInjector(new AbstractModule() {
protected void configure() {
bind(Boolean.class).toInstance(Boolean.TRUE);
}
});
#Test
public void methodInjection() {
Foo foo = i.getInstance(Foo.class);
assertThat(foo.x, is(true));
}
// EDIT: An example based on the comment by #JeffBowman
#Test
public void memberInjection() {
Foo foo = new Foo();
i.injectMembers(foo);
assertThat(foo.x, is(true));
}
}
If your real world class has a need to mix Guice controlled dependencies with client provided dependencies during construction have a look at assisted inject

Dependency Injection with constructor arguments

I've an EJB as follows:
public class Bar() {
private String s;
public Bar() {
this.s = "bar";
}
#Inject public Bar(String s) {
this.s = s;
}
}
How can I inject that bean by using the arg-constructor into another Foo class?
Then, I define the Foo class as EJB, with the aim to perform the DI for it into another class (for instance, a WebServlet). How can I inject a Foo class instance by passing a String to properly set up Bar arg-constructor as inner-dependency?
Is there a better way to define Bar in order to achieve points above?
The annotated constructor injection tells CDI that whenever someone requests an instance of Bar to be injected, it should use the constructor marked with #Inject.
The CDI container then tries to get instances for all required constructor parameters and fails, because it can not deal with "String". It just doesn't know which String you mean.
You have to help the container resolving the dependency by using a Producer and a Qualifier to tell him what String you want. I just give you the simplest possible solution here:
public class Bar {
#Inject
public Bar(#Named("myString") String s) {
this.s = s;
}
}
And then another class (doesn't have to be an different class, but its much more readable):
public class MyStringProducer {
#Produces
#Named("myString")
public String getMyString() {
return ...; // whatever you want ... read JSON, parse properties, randomize ...
}
}
#Inject only works when you are injecting "managed" objects. String is not a managed object, thus this won;t work.
However, the following example should work (I have used spring here. Use the DI initializaton code according to the library you are using):
#Named
public class Foo {
#Inject
Bar bar;
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext("com.pkg1");
Foo foo = (Foo)ctx.getBean("foo");
System.out.println(foo.bar.getString());
}
}
#Named
public class Bar {
private String s;
public Bar() {
this.s = "bar";
}
#Inject
public Bar(Bar1 bar1) {
this.s = bar1.getS();
}
public String getString() {
return s;
}
}
#Named
class Bar1 {
private String s="bar1";
public String getS() {
return s;
}
}

Guice: injecting a parameter used in implementation of abstract method

Here is an example of the issue I've come across:
public interface IFoo { ... }
public abstract class Helper implements IFoo {
public Helper() { ... }
protected abstract X helperMethod();
}
public class Foo extends Helper {
private final String aaa;
#Inject
public Foo(String aaa) { this.aaa = aaa; }
#Override
X helperMethod() { doSomethingUsingWhatsInjected(aaa); }
}
The issue is that when I bind IFoo to Foo like this:
bind(IFoo.class).to(Foo.class).in(Singleton.class);
it appears like helperMethod() is being called before the aaa has been Injected since I'm seeing aaa as null. But if I instead don't use the class Helper and in-line all of its code directly in Foo, guice doesn't struggle.
What's the difference between these two approaches? Why is helperMethod() called before we know from where we're getting the implementation of IFoo? Can we use Helper along with injection?
Are you sure you're not calling helperMethod from within Helper's constructor? You omitted that part from the code you posted, but it would match the behavior you're seeing.
public class Test {
interface IFoo { }
static abstract class Helper implements IFoo {
Helper() { helperMethod(); }
abstract void helperMethod();
}
static class Foo extends Helper {
private final String aaa;
Foo(String aaa) { this.aaa = aaa; }
#Override
void helperMethod() { System.out.println(String.valueOf(aaa)); }
}
public static void main(String[] args) {
// Call helperMethod twice:
// once in the Helper.Helper(), once right here.
new Foo("expected").helperMethod();
// output:
// null
// expected
}
}
The first thing Foo does is implicitly call its superclass constructor, as if you typed super(); this necessarily happens as the very first statement in the subclass constructor. Consequently, this happens even before final variables like aaa are set, so your overridden method in Foo sees aaa as null. As in my example, this is not specific to Guice, but Guice injection can trigger the constructor just like anything else can.
This StackOverflow answer offers a more thorough discussion of this problem.

create an object before the super call in java

Considering that simple java code which would not work:
public class Bar extends AbstractBar{
private final Foo foo = new Foo(bar);
public Bar(){
super(foo);
}
}
I need to create an object before the super() call because I need to push it in the base class.
I don't want to use an initialization block and I don't want to do something like:
super(new Foo(bar)) in my constructor..
How can I send data to a base class before the super call ?
If Foo has to be stored in a field, you can do this:
public class Bar extends AbstractBar{
private final Foo foo;
private Bar(Foo foo) {
super(foo);
this.foo = foo;
}
public Bar(){
this(new Foo(bar));
}
}
Otherwise super(new Foo(bar)) looks pretty legal for me, you can wrap new Foo(bar) into a static method if you want.
Also note that field initializers (as in your example) and initializer blocks won't help either, because they run after the superclass constructor. If field is declared as final your example won't compile, otherwise you'll get null in superclass constructor.
thats not possible in java. the only possible solution is the new call in the super constructor.
if the foo object can be shared between instances you may declar it as static
public class Bar extends AbstractBar{
private static final Foo foo = new Foo(bar);
public Bar(){
super(foo);
}
}
if the super class is under your control, you can refactor it and use the template method pattern to pull the object into the constructor instead of pusing it from the subclass. this applys the hollywod principle: don't call us, we will call you ;)
public abstract class AbstractBar{
private Object thing;
public AbstractBar(){
this.thing = this.createThatThing();
}
protected abstract Object createThatThing();
}
public class Bar extends AbstractBar {
// no constructor needed
protected Object createThatThing(){
return new Thing();
}
}
class AbstractBar{
public AbstractBar() {
}
public AbstractBar(Foo t) {
}
}
class Bar extends AbstractBar{
static Foo t=null;
public Bar() {
super(t=new Foo());
}
}
class Foo{...}

Categories