Suppose I have the following service interfaces defined (as well as implementations):
interface Service1 { /* Methods omitted for brevity */ }
interface Service2 { /* Methods omitted for brevity */ }
I also have this interface that cannot be modified (it's out of my hands):
interface YouAreNotAllowedToModifyMe {
Object createSomething();
}
Further suppose that I have a class that implements the YouAreNotAllowedToModifyMe
interface and accepts implementations of those services along with the current HttpServletRequest
. Note that the request is an implementation detail and NOT part of the interface.
class Demo implements YouAreNotAllowedToModifyMe {
private final HttpServletRequest request;
private final Service1 service1;
private final Service2 service2;
@Inject
public Demo(HttpServletRequest request, Service1 service1, Service2 service2) {
this.request = request;
this.service1 = service1;
this.service2 = service2;
}
public Object createSomething() {
// Use the request, service1, and service2 in order to create the object.
}
}
Demo
cannot be instantiated until runtime because it requires the current HttpServletRequest
, however I would like CDI injection to take care of injecting the other parameters. How can I do that?
Essentially, I would like for this to be possible (it's not):
class Foo {
@Inject
private final Instance<Demo> demoInstance;
public void doSomething(HttpServletRequest request) {
// This is pretend. This won't really work, though I wish it would.
// Essentially, I pass in the request and CDI takes care of everything else.
Demo demo = demoInstance.get(request);
}
}
You cannot use a constructor with half arguments injected and half provided by hand. You have however alternatives:
HttpServletRequest
. Better yet, use Delta Spike. Then you can actually inject the HttpServletRequest
!Modify Demo
to be a factory for instances of YouAreNotAllowedToModifyMe
, rather than implementing it:
@ApplicationScoped //probably-but not necessarily???
public class Demo {
@Inject
private final Service1 service1;
@Inject
private final Service2 service2;
public YouAreNotAllowedToModifyMe makeYouAreNotAllowedToModifyMe(HttpServletRequest request) {
return new YouAreNotAllowedToModifyMeImpl(request);
}
private class YouAreNotAllowedToModifyMeImpl implements YouAreNotAllowedToModifyMe {
YouAreNotAllowedToModifyMeImpl(HttpServletRequest request) {
// do what you must...
}
// implement it!
// remember, you can actually use service1 &
// service 2 from the enclosing instance
}
}