Search code examples
javadependency-injectioncdijsf-2.2oracle-adf

CDI injection of types in heirarchy


I have a supertype (CaseDTO) with a couple subtypes (GroupCaseDTO, IPCaseDTO) that I want to inject. Dev environment is JDev 12c.

Here are the two injection points:

  1. Injecting the supertype (this injection point works with both subtypes):

    @Inject @CaseContext private CaseDTO muwCase;

  2. Inject a specific subtype (this injection point works with only one subtype):

    @Inject @CaseContext private GroupCaseDTO muwCase;

To get these values, I have tried to setup a number of producer methods:

// supertype
@Produces @CaseContext
public CaseDTO getContextCase()  {
    return JSFUtils.getFromPageFlowScope("case", CaseDTO.class);
}

// subtype 1
@Produces @CaseContext
public IPCaseDTO getContextIpCase()  {
    return JSFUtils.getFromPageFlowScope("case", IPCaseDTO.class);
}

// subtype 2
@Produces @CaseContext
public GroupCaseDTO getContextGroupCase()  {
    return JSFUtils.getFromPageFlowScope("case", GroupCaseDTO.class);
}

The issue is, if I include only the supertype producer method, then the subtype injection point doesn't work:

:org.jboss.weld.exceptions.DeploymentException:WELD-001408: Unsatisfied dependencies for type GroupCaseDTO with qualifiers @CaseContext
at injection point [BackedAnnotatedField] @Inject @CaseContext private ca.bluecross.ab.muw.view.controller.decision.ManageGrpDecisionController.muwCase
at ca.bluecross.ab.muw.view.controller.decision.ManageGrpDecisionController.muwCase(ManageGrpDecisionController.java:0)
WELD-001475: The following beans match by type, but none have matching qualifiers:
- Managed Bean [class ca.bluecross.ab.muw.model.type.dto.grp.GroupCaseDTO] with qualifiers [@Any @Default]

But if I include all three producer methods, I get this exception on the supertype injection point:

:org.jboss.weld.exceptions.DeploymentException:WELD-001409: Ambiguous dependencies for type CaseDTO with qualifiers @CaseContext
at injection point [BackedAnnotatedField] @Inject @CaseContext private ca.bluecross.ab.muw.view.controller.UploadAssociatedDocumentController.muwCase
at ca.bluecross.ab.muw.view.controller.UploadAssociatedDocumentController.muwCase(UploadAssociatedDocumentController.java:0)
Possible dependencies: 
  - Producer Method [CaseDTO] with qualifiers [@CaseContext @Any] declared as [[BackedAnnotatedMethod] @Produces @CaseContext public ca.bluecross.ab.muw.view.util.DataContextHelper.getContextCase()],
  - Producer Method [GroupCaseDTO] with qualifiers [@CaseContext @Any] declared as [[BackedAnnotatedMethod] @Produces @CaseContext public ca.bluecross.ab.muw.view.util.DataContextHelper.getContextGroupCase()],
  - Producer Method [IPCaseDTO] with qualifiers [@CaseContext @Any] declared as [[BackedAnnotatedMethod] @Produces @CaseContext public ca.bluecross.ab.muw.view.util.DataContextHelper.getContextIpCase()]

Having just the two subtype producer methods doesn't work either:

:org.jboss.weld.exceptions.DeploymentException:WELD-001409: Ambiguous dependencies for type CaseDTO with qualifiers @CaseContext
  at injection point [BackedAnnotatedField] @Inject @CaseContext private ca.bluecross.ab.muw.view.controller.UploadAssociatedDocumentController.muwCase
  at ca.bluecross.ab.muw.view.controller.UploadAssociatedDocumentController.muwCase(UploadAssociatedDocumentController.java:0)
  Possible dependencies: 
  - Producer Method [GroupCaseDTO] with qualifiers [@CaseContext @Any] declared as [[BackedAnnotatedMethod] @Produces @CaseContext public ca.bluecross.ab.muw.view.util.DataContextHelper.getContextGroupCase()],
  - Producer Method [IPCaseDTO] with qualifiers [@CaseContext @Any] declared as [[BackedAnnotatedMethod] @Produces @CaseContext public ca.bluecross.ab.muw.view.util.DataContextHelper.getContextIpCase()]

I guess I can fix this by using a Qualifier annotation for each subtype that I need, but that seems excessive. Is there no way to get the injection working without a multitude of qualifier annotations?

In fact, here's what I want: one producer method + one qualifier annotation that allows me to inject the context case, regardless of it's subtype. Again, I don't think this is possible with CDI, as it's (too) strongly typed.


Solution

  • I think this is the best I can do; adapting @maress

    @Produces @CaseContext
    public CaseDTO getContextCase()  {
        return JSFUtils.getFromPageFlowScope("case", CaseDTO.class);
    }
    
    @Produces @CaseContext("ip")
    public IPCaseDTO getContextIpCase()  {
        return JSFUtils.getFromPageFlowScope("case", IPCaseDTO.class);
    }
    
    @Produces @CaseContext("group")
    public GroupCaseDTO getContextGroupCase()  {
        return JSFUtils.getFromPageFlowScope("case", GroupCaseDTO.class);
    }
    

    Annotation:

    @Qualifier
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ FIELD, METHOD })
    public @interface CaseContext {
        public String value() default "";
    }
    

    Then injection points

    @Inject @CaseContext
    private CaseDTO muwCase;
    
    @Inject @CaseContext("group")
    private GroupCaseDTO muwCase;
    
    @Inject @CaseContext("ip")
    private IPCaseDTO muwCase;