I am dealing with a design situation and I am not sure how to solve it or if I am doing anything wrong with my micro design.
public abstract class A implements SomeFrameworkInterface {
private final Param1 a1;
@Inject
private Param2 a2;
protected A(Param1 a1) {
this.a1 = a1;
}
@Override
public someFrameworkInterfaceMethod() {
//code
doMyStuff();
}
protected abstract void doMyStuff();
}
@Named
@SomeCustomAnnotation(property="someProperty")
public class B extends A {
@Inject
public B(Param1 b1) { //b1 is different for every implementation of class A, through some annotations
super(b1);
}
@Override
protected void doMyStuff() {
//code
}
}
- I need to change "@Inject Param2 a2" from class A to be injected through the constructor, so the code would be testable and I will clean a code smell associated with this.
- I don't want to send it from B constructor, because I would have to add one more argument in B constructor, in A constructor and for each constructor from all implementations of A... but the child class never needs to know about Param2 instance.
- Param2 may be static, but needs to be injected because it's component (@Named), so I didn't find a way to static inject.
Restrictions are the following:
- 3rd party framework with custom annotations to be used and interface to be implemented
- code must be testable, so @Inject/@Autowired on fields is not allowed
- we are restricted from using Spring which is "encapsulated" in the custom framework mentioned, so we can use only pure Java (JSR-330). (if any solution in Spring, would be nice to know about it too)
It's impossible to pass any parameter to A's constructor without going through B's, because you are actually constructing an instance of B. A's constructor is only delegated to in order to construct the "A part" of the B instance.
The most you can do is pass some sort of "typeless" parameter to B's constructor, so that at least B won't know about
Param2, but that cure already sounds worse than the disease even as I was writing it down...I don't see injecting
Param2post-construction making the code any less testable. OTOH, using a static field would most certainly do.