1

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?

lbilger
  • 304
  • 1
  • 8
  • Generics are a compile-time illusion. At runtime, they're represented as `Object` (use a bytecode viewer to confirm this), which could be the reason why you're having problems. As for avoiding `instanceof`, I actually [just answered a question about that](http://stackoverflow.com/questions/29458676/how-to-avoid-instanceof-when-implementing-factory-design-pattern/29459571#29459571) – Vince Apr 09 '15 at 16:42
  • You can use qualifiers, but one way or another you need to know about `AId`. – John Ament Apr 12 '15 at 15:12
  • 1
    What about adding additional method to ``Loader`` interface? Maybe something like: ``boolean canLoad(Object o)`` ? Then you will hide ``instanceof`` inside specifiec ``Loader`` implementation. – Arek Apr 17 '15 at 18:11

0 Answers0