Posted under CDI
Permalink
Tags Bug, CDI, Gotcha, Tip, Weld
Weld 1.0 was failing with “WELD-001408 Injection point has unsatisfied dependencies” when nested parameterised types were present.
The referenced bean was correctly present and annotated.
I found that I could work around the problem by simplifying/removing some of the generics. This allowed the beans to inject, but also gave warnings about the use of raw types. For example:-
//Original code
private @Inject TableCtrl<TreeNodePath<TaxonomyNode>, RowMetadata> selectionTable;//was replaced with the following
private @Inject TableCtrl<TreeNodePath, RowMetadata> selectionTable;
Attempts to use a CDI extension to find out more about what was happening did not reveal any more insight. This post discusses Weld performance and debugging and refers to a Stack Overflow post on the subject.
My solution to the problem (which I have also logged on Mantis) is as follows :-
- Injecting the bean into a raw type does not suffer from the problem.
- I therefore inject into a temporary raw type, and cast that to the correct type.
- Wrapping this in a method annotated with @Inject neatly solves the problem, as the method can take the raw types as arguments, and cast to the correctly parameterised fields in the method.
- As all this is done in a method, warnings can be suppressed for the method. This is a tidy solution, as the method only has this specific purpose, and no other warnings in the class are incorrectly suppressed.
- This is far better than the original workaround which involved hacking the generics back to non nested parameterised types throughout – this meant hacking a number of classes. The current solution entirely isolates the issue and allows the desired generics to be correctly used everywhere.
An example of the correct generic declarations and the method used follows :-
public abstract class TreeBrowser<N extends TreeNode<T>, T extends Tree<N>, P extends TreeNodePath<N>>
implements Serializable, BreadcrumbCtrlEvent<N> {
…
private CrumbComparator<N> crumbComparator;
private BreadcrumbCtrl<N> breadcrumb;
private TableCtrl<N, RowMetadata> treeNodeTable;
private TableCtrl<P, RowMetadataStatusMap> trayTable;
…
@Inject
@SuppressWarnings({"rawtypes", "unchecked"})
void injectWeldUnsatisfiedGenericBeans(CrumbComparator crumbComparator, BreadcrumbCtrl breadcrumb,
TableCtrl treeNodeTable, TableCtrl trayTable) {
this.crumbComparator = crumbComparator;
this.breadcrumb = breadcrumb;
this.treeNodeTable = treeNodeTable;
this.trayTable = trayTable;
}
This solved the problem.