...if the instance needs to be constructed manually, perhaps by a 3rd party factory class? Previously, (Jersey 1.x), you would do something like this:
public class MyInjectableProvider extends PerRequestTypeInjectableProvider<Context, MyInjectable> {
public MyInjectableProvider() {
super(MyInjectable.class);
}
@Override
public Injectable<MyInjectable> getInjectable(ComponentContext ic, Context context) {
MyInjectable myInjectableInstance = //...
return new Injectable<MyInjectable>() {
@Override
public MyInjectable getValue() {
return myInjectableInstance;
}
};
}
}
The anonymous local class is able to access an instance to return within some scope. This is useful when you're not working with classes that have default constructors, but they need to be constructed on a per-request basis.
Jersey 2.0 switched over to HK2 as a dependency injection framework, but alas, the migration page (https://jersey.java.net/documentation/latest/migration.html) doesn't provide an example of this kind of binding, and the HK2 documentation doesn't provide examples using an AbstractBinder.
To elaborate just a bit more, I'm trying to provide resource-local, container-agnostic JPA EntityManager instances to my resources. These have to be fetched from a singleton factory class, and should only stick around for a single "unit of work," which is a request in my case. I'm aware there are workarounds (Just inject the factory, or bind to a threadlocal), but I found the previous solution elegant and would like to recreate it if possible.
EDIT:
After digging through the HK2 javadocs for a bit, I've discovered that something similar can be achieved as follows:
public class MyInjectableProvider extends AbstractBinder
implements Factory<MyInjectable> {
@Override
protected void configure() {
bindFactory(this).to(MyInjectable.class);
}
@Override
public MyInjectable provide() {
return getMyInjectable();
}
@Override
public void dispose(MyInjectable instance) {}
}
And to register it...
public class MyResourceConfig extends ResourceConfig {
public MyResourceConfig() {
register(new MyInjectableProvider());
}
}
This "seems to work," but it also seems a bit unclear. dispose() is never called, for example. Also, this binding seems to implicitly behave as RequestScoped. Modifying the configuration to bindFactory(this).to(MyInjectable.class).in(RequestScoped.class); doesn't appear to actually change the behavior. Am I missing something, or is this the intended solution?