wildfly - CDI typesafe resolution is not working in weld 2.2.6 when the the bean type parameter is a type variable -
the following code snipset works "weld-core-1.1.5.as71.final.jar" (the 1 used jboss 7.1.1), doesn't work "weld-core-impl-2.2.6.final.jar" (the 1 used wildfly 8.2).
public class client<t> { public interface spi<t> { t getsomething(); } @inject private spi<t> spi; // weld-001408: unsatisfied dependencies type spi<object> } public class spiimpl implements client.spi<integer> { @override public integer getsomething() { return 5; } }
why? cdi 1.2 specification:
a parameterized bean type considered assignable parameterized required type if have identical raw type , each parameter:
- the required type parameter , bean type parameter actual types identical raw type, and, if type parameterized, bean type parameter assignable required type parameter according these rules, or
- the required type parameter wildcard, bean type parameter actual type , actual type assignable upper bound, if any, of wildcard , assignable lower bound, if any, of wildcard, or
- the required type parameter wildcard, bean type parameter type variable , upper bound of type variable assignable or assignable upper bound, if any, of wildcard , assignable lower bound, if any, of wildcard, or
- the required type parameter actual type, bean type parameter type variable , actual type assignable upper bound, if any, of type variable, or
- the required type parameter , bean type parameter both type variables , upper bound of required type parameter assignable upper bound, if any, of bean type parameter.
so, according item #4, above code should work, shouldn't it?
edit 1: <-- see edit 2 before. there noticed cdi implementation doing expected should do, mistakenly thought didn't.
antonin stefanutti answer right: item #4 of mentioned specification don't apply. but, if actual type of type variable t known when inyectión point resolved, possible proper instance of spi
.
supouse client
class abstract , implementation specifies type of type parameter in class definition. in case, actual type can discovered , item #4 of specification apply.
how can resolved? means of introspection, using class#getgenericinterfaces()
operation, on actual class
of client
instance. this:
public class test { @inject private clientimpl clientimpl; public abstract static class client<t> { public interface spi<t> { t getsomething(); } // @inject inject don't work because cdi doesn't require when actual type of t can discovered. so, instead, initialized programaticaly in postconstruct() private spi<t> spi; // weld-001408: unsatisfied dependencies type spi<object> // not true, later, in "edit 2" noteced works fine. forget this. sorry. @inject private instance<spi<?>> spifinder; /**initializes spi instance variable programaticaly */ @postconstruct private void postconstruct(){ parameterizedtype clienttype = (parameterizedtype)this.getclass().getgenericsuperclass(); type clienttypeparamter = clienttype.getactualtypearguments()[0]; class<t> clientparameterclass = (class<t>)clienttypeparamter; final iterator<spi<?>> iterator = spifinder.iterator(); while (iterator.hasnext()) { spi<?> spicandidate = iterator.next(); parameterizedtype spicandidatetype = (parameterizedtype)spicandidate.getclass().getgenericinterfaces()[0]; type spicandidatetypeparameter = spicandidatetype.getactualtypearguments()[0]; class<?> spicandidateparameterclass = (class<?>)spicandidatetypeparameter; if( clientparameterclass.isassignablefrom(spicandidateparameterclass)) { if( spi != null) throw new ambiguousresolutionexception(); spi = (spi<t>)spicandidate; } } if( spi == null) throw new unsatisfiedresolutionexception(); } } @dependent public static class spiimpl_1 implements client.spi<integer> { @override public integer getsomething() { return 5; } } @dependent public static class spiimpl_2 implements client.spi<double> { @override public double getsomething() { return 5.0; } } @dependent public static class clientimpl extends client<integer> {} }
the above code works (an instance of spiimpl_1
injected spi
instance variable), so, why couldn't cdi job us? instrospection it's possible discover actual type of every type parameter declared in enclosing class/interface definition when concrete class specifies actual type of extended superclass's type parameter.
edit 2 sorry, forget have said. cdi inject proper instance of client
in second example without need of programatic initialization added. doen't throw "weld-001408: unsatisfied dependencies type spi" said does. wrong. sorry again. should delete question?
in example, required type parameter type variable, t
, , not actual type item #4 not apply. actually, of conditions mentioned in specification assignability of parameterized bean type parameterized required type met in example, implies conclusively dependency not satisfied.
this somehow related cdi-517, though not identical, yet clarification can explain behavioral changes between weld 1.x , weld 2.x specification has been clarified.
as mentioned in discussion, having spi<integer>
assignable spi<t>
incorrect java langage standpoint.