Dependency Injection with constructor arguments - java

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;
}
}

Related

How to use Guice Injector to avoid declaring string as static

I'm actually new to using Guice injector. I have a situation where I have a String variable in one class and I want to use this variable in a different class without declaring it as static . Can I know how to use Guice injector here to avoid declaring it static
public class A {
private string a;
public void Method() {
a = "abc";
}
}
public class B {
public void method2() {
String b = a;
}
}
You can bind the directly to the instance of a string using the Names annotation.
bind(String.class).annotatedWith(Names.named("PROPERTY")).toInstance("Some String");
Although a better way to do it would be to use Properties:
// Your choice of loading properties
Properties properties = getPropreties();
Names.bindProperties(binder(), properties);
Then you can use either of these with
#Inject #Named("my.property") String myProperty;

How to run code after constructor in a Lombok builder

I have a class that I want to use Lombok.Builder and I need pre-process of some parameters. Something like this:
#Builder
public class Foo {
public String val1;
public int val2;
public List<String> listValues;
public void init(){
// do some checks with the values.
}
}
normally I would just call init() on a NoArg constructor, but with the generated builder I'm unable to do so. Is there a way for this init be called by the generated builder? For example build() would generate a code like:
public Foo build() {
Foo foo = Foo(params....)
foo.init();
return foo;
}
I'm aware that I can manually code the all args constructor, that the Builder will call through it and I can call init inside there.
But that is a sub-optimal solution as my class will likely have new fields added every once in a while which would mean changing the constructor too.
In Foo you could manually add a constructor, have that do the initialization, and put #Builder on the constructor. I know that you already know this, but I think it is the right solution, and you won't forget to add the parameter since you do want to use the code in the builder anyway.
Disclosure: I am a lombok developer.
After much trial and end error I found a suitable solution: extend the generate builder and call init() myself.
Example:
#Builder(toBuilder = true, builderClassName = "FooInternalBuilder", builderMethodName = "internalBuilder")
public class Foo {
public String val1;
public int val2;
#Singular public List<String> listValues;
void init() {
// perform values initialisation
}
public static Builder builder() {
return new Builder();
}
public static class Builder extends FooInternalBuilder {
Builder() {
super();
}
#Override public Foo build() {
Foo foo = super.build();
foo.init();
return foo;
}
}
}
I just stumbled upon the same issue. But additionally, I wanted to add an method buildOptional() to the builder to not repeat Optional.of(Foo) each time I need it. This did not work with the approach posted before because the chained methods return FooInternalBuilder objects; and putting buildOptional() into FooInternalBuilder would miss the init() method execution in Builder...
Also, I personally did not like the presence of 2 builder classes.
Here is what I did instead:
#Builder(buildMethodName = "buildInternal")
#ToString
public class Foo {
public String val1;
public int val2;
#Singular public List<String> listValues;
public void init(){
// do some checks with the values.
}
/** Add some functionality to the generated builder class */
public static class FooBuilder {
public Optional<Foo> buildOptional() {
return Optional.of(this.build());
}
public Foo build() {
Foo foo = this.buildInternal();
foo.init();
return foo;
}
}
}
You can do a quick test with this main method:
public static void main(String[] args) {
Foo foo = Foo.builder().val1("String").val2(14)
.listValue("1").listValue("2").build();
System.out.println(foo);
Optional<Foo> fooOpt = Foo.builder().val1("String").val2(14)
.listValue("1").listValue("2").buildOptional();
System.out.println(fooOpt);
}
Doing so let's you add what I want:
Add an init() method which is executed after each object construction automatically
Adding new fields do not require additional work (as it would be for an individually written constructor)
Possibility to add additional functionality (incl. the init() execution)
Retain the complete
standard functionality the #Builder annotation brings
Don't expose an additional builder class
Even if you solved your problem before I like to share this as the solution. It is a bit shorter and adds a (for me) nice feature.
This works for me, not a complete solution, but quick and easy.
#Builder
#AllArgsConstructor
public class Foo {
#Builder.Default
int bar = 42;
Foo init() {
// perform values initialisation
bar = 451; // replaces 314
return foo;
}
static Foo test() {
return new FooBuilder() // defaults to 42
.bar(314) // replaces 42 with 314
.build()
.init(); // replaces 314 with 451
}
}

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

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.

Guice example on how to correctly wire objects

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.

Categories