Recently I tried to solve a problem regarding CDI.
Let me explain:
To let the producer find its @Injects I define a @Qualifier.
Something like this:
Producer and consumer will not find each other.
Even the @ProxyProducer qualifier does not convince the CDI container to match producer and injection point.
The BaseInterface gets as a generic parameter its own sub interfaces:
If anybody has a better solution please let me know.
Let me explain:
The Situation
There are interfaces extending a base interface:public interface BaseInterface { ... } public interface InterfaceA extends BaseInterface { ... } public interface InterfaceB extends BaseInterface { ... } // and many more public interface InterfaceX extends BaseInterface { ... }Now I want a CDI producer injecting proxies for any sub-interface of the BaseInterface
To let the producer find its @Injects I define a @Qualifier.
Something like this:
@Qualifier public @interface ProxyProducer { } ... public class Consumer { @Inject @ProxyProducer InterfaceA proxyForInterfaceA; @Inject @ProxyProducer InterfaceB proxyForInterfaceB; ... } ... public class Producer { @Produces @ProxyProducer BaseInterface produceProxy(InjectionPoint ip) { Class> injectionPointClass = (Class>) ip.getType(); proxy = createDynamicProxy(injectionPointClass); return proxy; } BaseInterface createDynamicProxy(Class> interfaceClass) { // create and return dynamic proxy } }
The Problem
Too bad! It does not work.Producer and consumer will not find each other.
Even the @ProxyProducer qualifier does not convince the CDI container to match producer and injection point.
The Solution (at least the best I've found yet)
I saw this Stackoverflow about reading generic type parameters via reflection and came to the following solution:.The BaseInterface gets as a generic parameter its own sub interfaces:
public interface BaseInterface<T extends BaseInterface> { ... } public interface InterfaceA extends BaseInterface<InterfaceA> { ... } public interface InterfaceB extends BaseInterface<InterfaceB> { ... } ...The @Inject attributes are defined as a BaseInterface with the sub interface we need the proxy for as the generic parameter.
public class Consumer { @Inject @ProxyProducer BaseInterface<InterfaceA> proxyForInterfaceA; @Inject @ProxyProducer BaseInterface<InterfaceB> proxyForInterfaceB; ... }Now the producer can read the type parameter and create a proxy for it:
public class Producer { @Produces @ProxyProducer BaseInterface produceProxy(InjectionPoint ip) { Class<?> injectionPointClass = (Class<?>) ip.getType(); Class<?> interfaceClassToCreateProxyFor = (Class<?>) ((ParameterizedType) injectionPointClass.getGenericSuperclass()).getActualTypeArguments()[0]; proxy = createDynamicProxy(interfaceToCreateProxyFor); return proxy; } BaseInterface createDynamicProxy(Class> interfaceClass) { // create and return dynamic proxy } }Since producer and injection point are now of the same type BaseInterface the CDI container will match them together.
If anybody has a better solution please let me know.