Skip to content

Instantly share code, notes, and snippets.

@rmpestano
Last active December 12, 2019 13:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rmpestano/43d49cee7ca90418063b2b56f6acaef7 to your computer and use it in GitHub Desktop.
Save rmpestano/43d49cee7ca90418063b2b56f6acaef7 to your computer and use it in GitHub Desktop.
CDI bean selection

First I have 3 producers:

    @Produces
    public EntityManager produce() {
        return EntityManagerProvider.instance("cdipu").em();
    }

    @Produces
    @RiderPU("cdipu2") //just a CDI qualifier with a value attribute, like @Named
    public EntityManager produceEm2() {
        return EntityManagerProvider.instance("cdipu2").em();
    }

    @Produces
    @RiderPU("cdipu3")
    public EntityManager produceEm() {
        return EntityManagerProvider.instance("cdipu3").em();
    }

Secondly I can Inject the entity manager using the qualifier, it’s working because I see each producer method being called:

    @Inject
    EntityManager em;

    @Inject
    @RiderPU("cdipu2")
    EntityManager em2;

    @Inject
    @RiderPU("cdipu3")
    EntityManager em3;

The issue is when I try to lookup the entity manager based on the qualifier:

    @Inject
    private Instance<EntityManager> entityManagerInstance;


    public EntityManager getInstance(String puName) {
         return entityManagerInstance.select(EntityManager.class, new RiderPUAnnotation(puName){}).get();

    }
public class RiderPUAnnotation extends AnnotationLiteral<RiderPU> implements RiderPU {

    private final String value;

    public RiderPUAnnotation(final String value) {
        this.value = value;
    }

    public String value() {
        return value;
    }
}

The following error is thrown:

javax.enterprise.inject.UnsatisfiedResolutionException: Api type [javax.persistence.EntityManager] is not found with the qualifiers
Qualifiers: [@javax.enterprise.inject.Default(),@com.github.database.rider.cdi.api.RiderPU(value="cdipu2")]
for injection into Field Injection Point, field name :  entityManagerInstance, Bean Owner : [DataSetProcessor, WebBeansType:MANAGED, Name:null, API Types:[java.lang.Object,com.github.database.rider.cdi.DataSetProcessor], Qualifiers:[javax.enterprise.inject.Default,javax.enterprise.inject.Any]]
	at org.apache.webbeans.util.InjectionExceptionUtil.throwUnsatisfiedResolutionException(InjectionExceptionUtil.java:65)
	at org.apache.webbeans.inject.instance.InstanceImpl.get(InstanceImpl.java:120)
	at com.github.database.rider.cdi.DataSetProcessor.resolveEntityManager(DataSetProcessor.java:71)
	at com.github.database.rider.cdi.DataSetProcessor.init(DataSetProcessor.java:57)
	at com.github.database.rider.cdi.DataSetProcessor.process(DataSetProcessor.java:122)

CDI implementation is OpenWebBeans 1.6.2

@rmpestano
Copy link
Author

rmpestano commented Dec 11, 2019

Same happens with OpenWebBeans 2.0.13:

        <dependency>   
            <groupId>org.apache.openwebbeans</groupId>
            <artifactId>openwebbeans-impl</artifactId>
            <version>2.0.13</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.enterprise</groupId>
            <artifactId>cdi-api</artifactId>
            <version>2.0</version>
            <scope>test</scope>
        </dependency>

@struberg
Copy link

struberg commented Dec 12, 2019

Hi Rafael!

The behaviour is imo correct.
Your code is

    @Inject
    private Instance<EntityManager> entityManagerInstance;

That means you will get an Instance for @Default.
If you would like to get ALL EntityManager beans then you would need to use the @Any as per the spec. This is the version which should be perfectly portable.

    @Inject
    @Any
    private Instance<EntityManager> entityManagerInstance;

@rmpestano
Copy link
Author

Yes, that was the issue, thank you very much @struberg!

@rmpestano
Copy link
Author

rmpestano commented Dec 12, 2019

Also after adding @Inject @Any I also needed to add @Default on the default entityManager producer, otherwise I get Ambiguous beans when selecting beans without the @RiderPU qualifier, ex:

entityManagerInstance.select(EntityManager.class); 

Adding the default qualifier makes it work in both ways with and without RiderPU

    @Produces
    @Default
    public EntityManager produce() {
        return EntityManagerProvider.instance("cdipu").em();
    }

    @Produces
    @RiderPU("cdipu2") //just a CDI qualifier with a value attribute, like @Named
    public EntityManager produceEm2() {
        return EntityManagerProvider.instance("cdipu2").em();
    }

    @Produces
    @RiderPU("cdipu3")
    public EntityManager produceEm() {
        return EntityManagerProvider.instance("cdipu3").em();
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment