I am fairly new to JavaEE and also the concept of dependency injection. However I do have a fair understanding of it even though I do not know all the ways it can be used.
I have a Local Interface as below:
@Local
public interface MyInterfaceLocal {
SomeType getMeSometype();
}
The class that implements this interface is stateless EJB.
@Stateless
public class MyInterfaceImpl {
public SomeType getMeSomeType() {
//Some implementation details...
ExternalLibraryClass externalLib = new ExternalLibrary(arg1, arg2);
return externalLib.externalLibMethod();
}
}
Now the problem is, how can I avoid instantiating the externalLib
and let this be injected in someway? For example if this was another EJB that I created with an interface, then I could simply let the EJB container handle the instantiation, with an @EJB
annotation like below.
@Stateless
public class MyInterfaceImpl {
@EJB
AnotherInterface anotherInterfaceImpl;
public SomeOtherType getMeSomeType() {
//Some implementation details...
return anotherInterfaceImpl.someMethod();
}
}
I want to be able to do (something like) this for external library that I am using because, that allows me to:
MyInterfaceImpl
class.I have so far looked at-
Creating a wrapper method whose parameter is the ExternalLibrary
and thus can perform some kind of manual method parameter injection. This still makes my implementation tightly coupled to the underlying library. (Or I am not doing it right)
Using Context & Dependency Injection
container to do the injection (like how the EJB container does. I am aware its not the same). Researched about the ability of using Producers
. Although I understand what Producers
do with respect to CDI, I am not able to wrap my head around how I can make use of this? Or even if I am on the right path?
UPDATE: I found a few articles that helped me understand the CDI Producers better and I tried going by that approach but faced another problem. So now I have:
ExternalLibraryProducer.java
public class ExternalLibraryProducer {
@Produces
private ExternalLibraryClass1 extrnalLibraryClassProducer() {
return new ExternalLibraryClass1("SomeString", 7);
//The constructor actually takes a string and another commplex type
//as parameters. I am keeping it a little simple here.
//I am trying to set the ExternalLibraryClass1() arguments
//programmatically at runtime.
}
}
Now the constructor of the object that I want to produce, takes in parameters, lets say a String and integer. I thought I could create a Qualifier
to pass in these parameters to produce the object that I want.
ExternalLibraryClass1Qualifier.java
@Qualifier
@Retention(RUNTIME)
@Target({METHOD})
public @interface ExternalLibraryClass1Qualifier {
String argument1();
Int argyment2(); //This is actually another complex type. Keeping it
//simple here.
}
Now what I want to do is, I want the argument values to be set programmatically at runtime (assume, from a properties file). And I am not able to figure out how to do this. So my final injection would look like below.
@Stateless
public class MyInterfaceImpl {
@Inject
@ExternalLibraryClass1Qualifier(argument1 = "something", argument2 = 7)
ExternalLibrary externalLib;
public SomeType getMeSomeType() {
//Some implementation details...
return externalLib.externalLibMethod();
}
}
Thanks for any guidance.
CDI producers are a way to go here, the only question is, how exactly do you want to build them.
Since you said that the arguments come from a property file, I would suggest that you invert the approach and let producer method check that property file and extract the values (or ask any "reader" which did that before and caches it):
@Produces
private ExternalLibraryClass1 produceExternalLibraryInstance() {
// read the properties from the file or from any cache you use
String arg1 = PropertyReader.getarg1();
Integer arg2 = PropertyReader.getArg2();
// create object with those args
return new ExternalLibraryClass1(arg1, arg2);
}
With this you obviously need no qualifier and can then simply do @Inject ExternalLibraryClass1
.
Just note that producer will be invoked based on when you create an object which injects ExternalLibraryClass1
- make sure you can grab the args from property file this soon. (should't be trouble when produces does the reading, might be trickier if you have some cache in place)