0

Hi I have a following Qualifier Type defined..

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.FIELD })
public @interface SortAndFilterType {

/**
 * The value for the sort and filter.
 *
 * @return the sort and filter type value.
 */
String value();
}

And Two Implementations out of it.

@SortAndFilterType("Users")
public class UserSortAndFilterProviderImpl implements SortAndFilterProvider<Field, User>       {}

@SortAndFilterType("ReportsList")
public class ReportListSortAndFilterProviderImpl implements SortAndFilterProvider<Field, ReportList> {}

And I'm injecting from the Client as ..

@Inject
@SortAndFilterType("Users")
private SortAndFilterProvider mSortAndFilterProvider;

Every thing works fine at run time..

But the Problem comes when I ran Unit tests..

I'm getting the below Exception..

org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type SortAndFilterProvider with qualifiers @SortAndFilterType at injection point [BackedAnnotatedField] @Inject @SortAndFilterType private com.collabnet.ctf.saturn.client.apps.users.ChangeUsersStatus.mSortAndFilterProvider

I invoke this from unit tests like this..it runs with @RunWith(CdiRunner.class)

@Produces
@SortAndFilterType("Users")
@Mock
private SortAndFilterProvider mSortAndFilterProvider;

Whats going wrong here?

Jens Piegsa
  • 7,399
  • 5
  • 58
  • 106

2 Answers2

1

One nice thing with CDI (which is a problem for you here) is that its type safe resolution takes parameter in parameterized types into account. In other word : "no type erasure in CDI" The spec is very detailed about parameterized types resolution :

A parameterized bean type is considered assignable to a parameterized required type if they have identical raw type and for each parameter:

  • the required type parameter and the bean type parameter are actual types with identical raw type, and, if the type is parameterized, the bean type parameter is assignable to the required type parameter according to these rules, or

  • the required type parameter is a wildcard, the bean type parameter is an actual type and the actual type is assignable to the upper bound, if any, of the wildcard and assignable from the lower bound, if any, of the wildcard, or

  • the required type parameter is a wildcard, the bean type parameter is a type variable and the upper bound of the type variable is assignable to or assignable from the upper bound, if any, of the wildcard and assignable from the lower bound, if any, of the wildcard, or

  • the required type parameter is an actual type, the bean type parameter is a type variable and the actual type is assignable to the upper bound, if any, of the type variable, or

  • the required type parameter and the bean type parameter are both type variables and the upper bound of the required type parameter is assignable to the upper bound, if any, of the bean type parameter.

You can read the original text here : http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#assignable_parameters.

Now Weld 1.x is not enough strict with this point and accept to assign a parameterized type to its raw type. That's probably why you don't have issue at runtime (running with JBoss AS 7.x for instance) and have this problem in your test (cdi-runner is probably using Weld 2.x). Yes I'm guessing here and I may be wrong, that's why it's always a good thing to give version of framework you're using in your question.

Anyway you should resolve your problem by changing you injection point to

@Inject
@SortAndFilterType("Users")
private SortAndFilterProvider<Field,?> mSortAndFilterProvider; 

It respects the specification and will work under Weld 1.x and 2.x.

By the way you probably don't need your qualifier since there won't be any ambiguity between :

@Inject
private SortAndFilterProvider<Field,User> mSortAndFilterProvider1;

and

@Inject
private SortAndFilterProvider<Field,ReportList> mSortAndFilterProvider2;
Antoine Sabot-Durand
  • 4,875
  • 17
  • 33
0

Hi that's Exactly the Problem. and my Runtime uses Jboss 7 and the Test Environment uses CDI 2.x.

After adding the type parameters to the Injection point it works perfectly fine.

Thanks a lot.