Search code examples
javajakarta-eecdijava-ee-6java-ee-7

Correct way to get contextual reference of a Java CDI bean


I googled for the way to get contextual reference of a CDI bean. I found 2 ways:

1. Using beans.iterator()

    public static <T> T getReference(BeanManager bm, Class<? extends T> type, Annotation... qualifiers) {
        Set<Bean<?>> beans = bm.getBeans(type, qualifiers);
        if (beans == null || beans.isEmpty()) {
            throw new IllegalArgumentException("Bean not found.");
        }

        // Using beans.iterator()
        Bean<T> bean = (Bean<T>) beans.iterator().next();

        return (T) bm.getReference(bean, type, bm.createCreationalContext(bean));
    }

2. Using BeanManager.resolve

    public static <T> T getReference(BeanManager bm, Class<? extends T> type, Annotation... qualifiers) {
        Set<Bean<?>> beans = bm.getBeans(type, qualifiers);
        if (beans == null || beans.isEmpty()) {
            throw new IllegalArgumentException("Bean not found.");
        }

        // Using BeanManager.resolve()
        Bean<T> bean = (Bean<T>) bm.resolve(beans);

        return (T) bm.getReference(bean, type, bm.createCreationalContext(bean));
    }

My question is: Which way is correct? if both are correct, what is context use of each one?

Thank you!


Solution

  • The CDI specification distinguishes 3 stages for a bean while performing typesafe resolution:

    • Available: Java EE defines a series of accessibility rules for classloading, which CDI extends to cover bean resolution. For example a bean in a WAR can inject a bean in an ejb-jar, but not vice-versa,
    • Assignable: the bean has a bean type that matches the required type following Assignability of raw and parameterized types,
    • Resolved: the bean is elligible, that is both available and assignable, and it not ambiguous as specified in unsatisfied and ambiguous dependencies.

    The first way above retrieves all the elligible beans for the provided type and qualifiers and gets a contextual reference for the first elligible bean but does not resolve potential ambiguities, in case of alternatives.

    The second way, however, does perform resolution and returns a contextual reference of the resolved bean or throws AmbiguousResolutionException if resolution fails.

    So both ways are programmatically correct. Choosing one over the other depends on the context. Though the second way is prefered in doubt as it is exactly reproducing what the container is doing when performing injection but in a programmatic manner.