I sometimes come across a situation where I want to select a suitable implementation of some generic interface based on the runtime type of some object. I would like to do this using CDI. Example of what I would like to do:
public interface Id {}
public interface AId extends Id {
String getAValue();
}
public interface BId extends Id {
Integer getBValue();
}
public interface Loader<I extends Id> {
Object load(I id);
}
public class ALoader implements Loader<AId> {
public Object load(AId id) {
return id.getAValue();
}
}
public class BLoader implements Loader<BId> {
public Object load(BId id) {
return id.getBValue();
}
}
public class MyCdiBean {
@Inject
private Instance<Loader> loaders;
public <I extends Id> Object loadSomething(I id) {
return loaders.select(new TypeLiteral<Loader<I>>() {}).get().load(id);
}
}
Of course, the new TypeLiteral<Loader<I>>() {}
does not work because CDI can't determine the type of I
through the reflection API (or so I think), but I hope it makes clear what I want to do: I want to select the CDI bean based on its generic type argument using the runtime type of my variable.
I know I could do
public class MyCdiBean {
@Inject
private Loader<AId> aLoader;
@Inject
private Loader<BId> bLoader;
public Object loadSomething(Id id) {
if (id instanceof AId) {
return aLoader.load((AId)id);
}
return bLoader.load((BId) id);
}
}
but I would like to avoid the instanceof
checks (basically, I would like it to work without MyCdiBean
knowing about AId
and BId
).
I also know it would work using a qualifier annotation, though not in a completely typesafe way.
Is there any other clean way to do this? What do you see as a good way to solve this problem?