2

Given the type:

public interface Foo<T, X extends A>{...}

I need to use programmatic lookup to find bean that implement the given interface regardless of parameter types. Because of type safe resolution this returns an empty set:

final Set<Bean<?>> foos= BeanManagerProvider.getInstance().getBeanManager().getBeans(Foo.class, new AnyLit());

or via Deltaspike:

org.apache.deltaspike.core.api.provider.BeanProvider.getDependent(Foo.class, new AnyLit())

where AnyLit is:

private static class AnyLit extends AnnotationLiteral<Any> implements Any
{

}

Is there any way to get around this?

Thanks

Gee2113
  • 258
  • 2
  • 11

2 Answers2

2

I think you could make use of TypeLiteral - a special CDI class which can hold the type and it's parameters. Through this you can specify what exactly you want in approximately this way:

TypeLiteral<Foo<Object, Object>> typeLiteral = new TypeLiteral<Foo<Object, Object>>() {};
BeanManager bm; //assuming you can retrieve BM somehow
bm.getBeans(typeLiteral.getType(), new AnyLit());

Now, this is (I hope) in accord with CDI assignability rules (WARNING: generics ahead, grab a coffee before reading). In short, you want to use Object as a type so that:

  • It finds all other types, such as bar <Bar> (which are all assignable to Object)
  • Parameters, such as FooImpl<T> implements Foo<T> will also be assignable to Object
  • It also finds raw type beans, such as MyFoo implements Foo
Siliarus
  • 6,393
  • 1
  • 14
  • 30
  • I took your idea here and got it working for my use case - although its a little ugly it works as expected. Thanks – Gee2113 Jun 22 '17 at 08:00
  • You are welcome. Btw it isn't really ugly - I mean there is no other way than having an extra class which holds the type parameter. This is not really a CDI limitation but rather Java's. Due to type erasure you lose this information, hence you need to make up for it elsewhere. – Siliarus Jun 22 '17 at 09:15
0

Have a look at the Instance bean which is provided by the container and do something like:

@Any
@Inject
private Instance<MyInterface<?>> myParametrizedInterfaces;

The Instance bean is an Iterable, which means you can iterate over all beans implementing the said interface

Notice the ? generic parameter. In this case all generic parameters will match (java generics)

maress
  • 3,533
  • 1
  • 19
  • 37
  • Instance works fine, however in my use case i need to look up beans statically. Im basically wrapping deltaspikes DependentProvider (or similar approach to getting dependent beans) so that it auto disposes of dependent scoped beans after use to prevent memory leaks when calling in app scoped beans. Thanks though your answer will be useful to some – Gee2113 Jun 22 '17 at 07:59