Dependency Injection with constructor arguments
-
26-12-2019 - |
Question
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 aFoo
class instance by passing aString
to properly set upBar
arg-constructor as inner-dependency?Is there a better way to define
Bar
in order to achieve points above?
Solution
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 ...
}
}
OTHER TIPS
@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;
}
}