Loading...

Restricting the bean types of a bean in CDI

:heavy_exclamation_mark: This post is older than a year. Consider some information might not be accurate anymore. :heavy_exclamation_mark:

The bean types of a bean may be restricted by annotating the bean class or producer method or field with the annotation @javax.enterprise.inject.Typed.

We have 2 bean implementations:

public class CnfgParamMapper {}

Second bean extends from first bean

public class CnfgParamSetMapper extends CnfgParamMapper {}

Now you want to inject either one or both beans, you will stumble over an exception.

@RunWith(CdiRunner.class)
public class CnfgParamMapperTest {
    @Inject private CnfgParamMapper cnfgParamMapper;
    @Inject private CnfgParamSetMapper cnfgParamSetMapper;
    //..
}

The exception more in detail

org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type CnfgParamMapper with qualifiers @Default
  at injection point [UnbackedAnnotatedField] @Inject private net.cinhtau.parser.mapping.element.CnfgParamMapperTest.cnfgParamMapper
  at net.cinhtau.parser.mapping.element.CnfgParamMapperTest.cnfgParamMapper(CnfgParamMapperTest.java:0)
  Possible dependencies:
  - Managed Bean [class net.cinhtau.parser.mapping.element.CnfgParamMapper] with qualifiers [@Any @Default],
  - Managed Bean [class net.cinhtau.parser.mapping.element.CnfgParamSetMapper] with qualifiers [@Any @Default]

Since CnfgParamSetMapper extends from CnfgParamMapper, it is also eligible for injection. The type is resolved to:

  • CnfgParamMapperCnfgParamMapper.class, Object.class
  • CnfgParamSetMapperCnfgParamMapper.class, CnfgParamSetMapper.class, Object.class

By injecting CnfgParamMapper, weld can’t distinguish which one is the correct one, so it is ambiguous.

Solution

To avoid the ambiguous situation above, we restrict the types by explicitly defining the type for injection on the bean implementations.

first bean

@Typed(value = { CnfgParamMapper.class })
public class CnfgParamMapper {}

second bean

@Typed(value = { CnfgParamSetMapper.class })
public class CnfgParamSetMapper extends CnfgParamMapper {}

As we only define the CnfgParamSetMapper.class, we explicitly removed the superclass (CnfgParamMapper.class) from the bean type resolution.