Chapter 5. Dependency injection, lookup and EL

The container injects references to contextual instances to the following kinds of injection point:

References to contextual instances may also be obtained by programmatic lookup or by Unified EL expression evaluation.

In general, a bean type or bean EL name does not uniquely identify a bean. When resolving a bean at an injection point, the container considers bean type, qualifiers and alternative declarations in beans.xml. When resolving a name in an EL expression, the container considers the bean name and alternative declarations in beans.xml. This allows bean developers to decouple type from implementation.

The container is required to support circularities in the bean dependency graph where at least one bean participating in every circular chain of dependencies has a normal scope, as defined in Section 6.3, “Normal scopes and pseudo-scopes”. The container is not required to support circular chains of dependencies where every bean participating in the chain has a pseudo-scope.

5.1. Modularity

Beans and their clients may be deployed in modules in a module architecture such as the Java EE environment. In a module architecture, certain modules are considered bean archives. In the Java EE module architecture, any Java EE module or library is a module. The Java EE module or library is a bean archive if it contains a beans.xml file, as defined in Section 12.1, “Bean archives”.

A bean packaged in a certain module is available for injection, lookup and EL resolution to classes and JSP/JSF pages packaged in some other module if and only if the bean class of the bean is required to be accessible to the other module by the class accessibility requirements of the module architecture. In the Java EE module architecture, a bean class is accessible in a module if and only if it is required to be accessible according to the class loading requirements defined by the Java EE platform specification.

Note that, in some Java EE implementations, a bean class might be accessible to some other class even when this is not required by the Java EE platform specification. For the purposes of this specification, a class is not considered accessible to another class unless accessibility is explicitly required by the Java EE platform specification.

An alternative is not available for injection, lookup or EL resolution to classes or JSP/JSF pages in a module unless the module is a bean archive and the alternative is explicitly selected in that bean archive. An alternative is never available for injection, lookup or EL resolution in a module that is not a bean archive.

5.1.1. Declaring selected alternatives for a bean archive

By default, a bean archive has no selected alternatives. An alternative must be explicitly declared using the <alternatives> element of the beans.xml file of the bean archive. The <alternatives> element contains a list of bean classes and stereotypes. An alternative is selected for the bean archive if either:

  • the alternative is a managed bean or session bean and the bean class of the bean is listed,

  • the alternative is a producer method, field or resource, and the bean class that declares the method or field is listed, or

  • any @Alternative stereotype of the alternative is listed.

<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
   <alternatives>
      <class>org.mycompany.myfwk.InMemoryDatabase</class>
      <stereotype>org.mycompany.myfwk.Mock</stereotype>
      <stereotype>org.mycompany.site.Australian</stereotype>
   </alternatives>
</beans>

Each child <class> element must specify the name of an alternative bean class. If there is no class with the specified name, or if the class with the specified name is not an alternative bean class, the container automatically detects the problem and treats it as a deployment problem.

Each child <stereotype> element must specify the name of an @Alternative stereotype annotation. If there is no annotation with the specified name, or the annotation is not an @Alternative stereotype, the container automatically detects the problem and treats it as a deployment problem.

If the same type is listed twice under the <alternatives> element, the container automatically detects the problem and treats it as a deployment problem.

For a custom implementation of the Bean interface defined in Section 11.1, “The Bean interface”, the container calls isAlternative() to determine whether the bean is an alternative, and getBeanClass() and getStereotypes() to determine whether an alternative is selected in a certain bean archive.

5.1.2. Enabled and disabled beans

A bean is said to be enabled if:

  • it is deployed in a bean archive, and

  • it is not a producer method or field of a disabled bean, and

  • it is not specialized by any other enabled bean, as defined in Section 4.3, “Specialization”, and either

  • it is not an alternative, or it is a selected alternative of at least one bean archive.

Otherwise, the bean is said to be disabled.

Note that Section 3.12, “@New qualified beans” defines a special rule that determines whether a @New qualified bean is enabled or disabled. This rule applies as only to @New qualified beans, as an exception to the normal rule defined here.

5.1.3. Inconsistent specialization

Suppose an enabled bean X specializes a second bean Y. If there is another enabled bean that specializes Y we say that inconsistent specialization exists. The container automatically detects inconsistent specialization and treats it as a deployment problem.

5.1.4. Inter-module injection

A bean is available for injection in a certain module if:

  • the bean is not an interceptor or decorator,

  • the bean is enabled,

  • the bean is either not an alternative, or the module is a bean archive and the bean is a selected alternative of the bean archive, and

  • the bean class is required to be accessible to classes in the module, according to the class accessibility requirements of the module architecture.

For a custom implementation of the Bean interface defined in Section 11.1, “The Bean interface”, the container calls getBeanClass() to determine the bean class of the bean and InjectionPoint.getMember() and then Member.getDeclaringClass() to determine the class that declares an injection point.

5.2. Typesafe resolution

The process of matching a bean to an injection point is called typesafe resolution. The container considers bean type and qualifiers when resolving a bean to be injected to an injection point. The type and qualifiers of the injection point are called the required type and required qualifiers. Typesafe resolution usually occurs at application initialization time, allowing the container to warn the user if any enabled beans have unsatisfied or unresolvable ambiguous dependencies.

A bean is assignable to a given injection point if:

  • The bean has a bean type that matches the required type. For this purpose, primitive types are considered to match their corresponding wrapper types in java.lang and array types are considered to match only if their element types are identical. Parameterized and raw types are considered to match if they are identical or if the bean type is assignable to the required type, as defined in Section 5.2.3, “Assignability of raw and parameterized types” or Section 8.3.1, “Assignability of raw and parameterized types for delegate injection points”.

  • The bean has all the required qualifiers. If no required qualifiers were explicitly specified, the container assumes the required qualifier @Default. A bean has a required qualifier if it has a qualifier with (a) the same type and (b) the same annotation member value for each member which is not annotated @javax.enterprise.util.Nonbinding.

A bean is eligible for injection to a certain injection point if:

For a custom implementation of the Bean interface defined in Section 11.1, “The Bean interface”, the container calls getTypes() and getQualifiers() to determine the bean types and qualifiers.

5.2.1. Unsatisfied and ambiguous dependencies

An unsatisfied dependency exists at an injection point when no bean is eligible for injection to the injection point. An ambiguous dependency exists at an injection point when multiple beans are eligible for injection to the injection point.

Note that an unsatisfied or ambiguous dependency cannot exist for a decorator delegate injection point, defined in Section 8.1.2, “Decorator delegate injection points”.

When an ambiguous dependency exists, the container attempts to resolve the ambiguity. The container eliminates all eligible beans that are not alternatives, except for producer methods and fields of beans that are alternatives. If there is exactly one bean remaining, the container will select this bean, and the ambiguous dependency is called resolvable.

The container must validate all injection points of all enabled beans and of all other Java EE component classes supporting injection when the application is initialized to ensure that there are no unsatisfied or unresolvable ambiguous dependencies. If an unsatisfied or unresolvable ambiguous dependency exists, the container automatically detects the problem and treats it as a deployment problem.

For a custom implementation of the Bean interface defined in Section 11.1, “The Bean interface”, the container calls getInjectionPoints() to determine the set of injection points.

5.2.2. Legal injection point types

Any legal bean type, as defined in Section 2.2.1, “Legal bean types” may be the required type of an injection point. Furthermore, the required type of an injection point may contain a wildcard type parameter. However, a type variable is not a legal injection point type.

If an injection point type is a type variable, the container automatically detects the problem and treats it as a definition error.

5.2.3. Assignability of raw and parameterized types

A parameterized bean type is considered assignable to a raw required type if the raw types are identical and all type parameters of the bean type are either unbounded type variables or java.lang.Object.

A parameterized bean type is considered assignable to a parameterized required type if they have identical raw type and for each parameter:

  • the required type parameter and the bean type parameter are actual types with identical raw type, and, if the type is parameterized, the bean type parameter is assignable to the required type parameter according to these rules, or

  • the required type parameter is a wildcard, the bean type parameter is an actual type and the actual type is assignable to the upper bound, if any, of the wildcard and assignable from the lower bound, if any, of the wildcard, or

  • the required type parameter is a wildcard, the bean type parameter is a type variable and the upper bound of the type variable is assignable to or assignable from the upper bound, if any, of the wildcard and assignable from the lower bound, if any, of the wildcard, or

  • the required type parameter is an actual type, the bean type parameter is a type variable and the actual type is assignable to the upper bound, if any, of the type variable, or

  • the required type parameter and the bean type parameter are both type variables and the upper bound of the required type parameter is assignable to the upper bound, if any, of the bean type parameter.

For example, Dao is eligible for injection to any injection point of type @Default Dao<Order>, @Default Dao<User>, @Default Dao<?>, @Default Dao<? extends Persistent> or @Default Dao<X extends Persistent> where X is a type variable.

public class Dao<T extends Persistent> { ... }

Furthermore, UserDao is eligible for injection to any injection point of type @Default Dao<User>, @Default Dao<?>, @Default Dao<? extends Persistent> or @Default Dao<? extends User>.

public class UserDao extends Dao<User> { ... }

Note that a special set of rules, defined in Section 8.3.1, “Assignability of raw and parameterized types for delegate injection points”, apply if and only if the injection point is a decorator delegate injection point.

5.2.4. Primitive types and null values

For the purposes of typesafe resolution and dependency injection, primitive types and their corresponding wrapper types in the package java.lang are considered identical and assignable. If necessary, the container performs boxing or unboxing when it injects a value to a field or parameter of primitive or wrapper type.

However, if an injection point of primitive type resolves to a bean that may have null values, such as a producer method with a non-primitive return type or a producer field with a non-primitive type, the container automatically detects the problem and treats it as a deployment problem.

For a custom implementation of the Bean interface defined in Section 11.1, “The Bean interface”, the container calls isNullable() to determine whether the bean may have null values.

5.2.5. Qualifier annotations with members

Qualifier types may have annotation members.

@PayBy(CHEQUE) class ChequePaymentProcessor implements PaymentProcessor { ... }
@PayBy(CREDIT_CARD) class CreditCardPaymentProcessor implements PaymentProcessor { ... }

Then only ChequePaymentProcessor is a candidate for injection to the following attribute:

@Inject @PayBy(CHEQUE) PaymentProcessor paymentProcessor;

On the other hand, only CreditCardPaymentProcessor is a candidate for injection to this attribute:

@Inject @PayBy(CREDIT_CARD) PaymentProcessor paymentProcessor;

The container calls the equals() method of the annotation member value to compare values.

An annotation member may be excluded from consideration using the @Nonbinding annotation.

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface PayBy {
    PaymentMethod value();
    @Nonbinding String comment() default "";
}

Array-valued or annotation-valued members of a qualifier type should be annotated @Nonbinding in a portable application. If an array-valued or annotation-valued member of a qualifier type is not annotated @Nonbinding, non-portable behavior results.

5.2.6. Multiple qualifiers

A bean class or producer method or field may declare multiple qualifiers.

@Synchronous @PayBy(CHEQUE) class ChequePaymentProcessor implements PaymentProcessor { ... }

Then ChequePaymentProcessor would be considered a candidate for injection into any of the following attributes:

@Inject @PayBy(CHEQUE) PaymentProcessor paymentProcessor;
@Inject @Synchronous PaymentProcessor paymentProcessor;
@Inject @Synchronous @PayBy(CHEQUE) PaymentProcessor paymentProcessor;

A bean must declare all of the qualifiers that are specified at the injection point to be considered a candidate for injection.

5.3. EL name resolution

The process of matching a bean to a name used in EL is called name resolution. Since there is no typing information available in EL, the container may consider only the EL name. Name resolution usually occurs at runtime, during EL expression evaluation.

An EL name resolves to a bean if:

  • the bean has the given EL name, and
  • the bean is available for injection in the war containing the JSP or JSF page with the EL expression.

For a custom implementation of the Bean interface defined in Section 11.1, “The Bean interface”, the container calls getName() to determine the bean EL name.

5.3.1. Ambiguous EL names

An ambiguous EL name exists in an EL expression when an EL name resolves to multiple beans. When an ambiguous EL name exists, the container attempts to resolve the ambiguity. The container eliminates all beans that are not alternatives, except for producer methods and fields of beans that are alternatives. If there is exactly one bean remaining, the container will select this bean, and the ambiguous EL name is called resolvable.

All unresolvable ambiguous EL names are detected by the container when the application is initialized. Suppose two beans are both available for injection in a certain war, and either:

  • the two beans have the same EL name and the name is not resolvable, or

  • the EL name of one bean is of the form x.y, where y is a valid bean EL name, and x is the EL name of the other bean,

the container automatically detects the problem and treats it as a deployment problem.

5.4. Client proxies

An injected reference, or reference obtained by programmatic lookup, is usually a contextual reference as defined by Section 6.5.3, “Contextual reference for a bean”.

A contextual reference to a bean with a normal scope, as defined in Section 6.3, “Normal scopes and pseudo-scopes”, is not a direct reference to a contextual instance of the bean (the object returned by Contextual.create()). Instead, the contextual reference is a client proxy object. A client proxy implements/extends some or all of the bean types of the bean and delegates all method calls to the current instance (as defined in Section 6.3, “Normal scopes and pseudo-scopes”) of the bean.

There are a number of reasons for this indirection:

  • The container must guarantee that when any valid injected reference to a bean of normal scope is invoked, the invocation is always processed by the current instance of the injected bean. In certain scenarios, for example if a request scoped bean is injected into a session scoped bean, or into a servlet, this rule requires an indirect reference. (Note that the @Dependent pseudo-scope is not a normal scope.)

  • The container may use a client proxy when creating beans with circular dependencies. This is only necessary when the circular dependencies are initialized via a managed bean constructor or producer method parameter. (Beans with scope @Dependent never have circular dependencies.)

  • Finally, client proxies may be passivated, even when the bean itself may not be. Therefore the container must use a client proxy whenever a bean with normal scope is injected into a bean with a passivating scope, as defined in Section 6.6, “Passivation and passivating scopes”. (On the other hand, beans with scope @Dependent must be serialized along with their client.)

Client proxies are never required for a bean whose scope is a pseudo-scope such as @Dependent.

Client proxies may be shared between multiple injection points. For example, a particular container might instantiate exactly one client proxy object per bean. (However, this strategy is not required by this specification.)

5.4.1. Unproxyable bean types

Certain legal bean types cannot be proxied by the container:

  • classes which don't have a non-private constructor with no parameters,

  • classes which are declared final or have final methods,

  • primitive types,

  • and array types.

If an injection point whose declared type cannot be proxied by the container resolves to a bean with a normal scope, the container automatically detects the problem and treats it as a deployment problem.

5.4.2. Client proxy invocation

Every time a method of the bean is invoked upon a client proxy, the client proxy must:

If the scope is not active, as specified in Section 6.5.1, “The active context object for a scope”, the client proxy rethrows the ContextNotActiveException or IllegalStateException.

The behavior of all methods declared by java.lang.Object, except for toString(), is undefined for a client proxy. Portable applications should not invoke any method declared by java.lang.Object, except for toString(), on a client proxy.

5.5. Dependency injection

From time to time the container instantiates beans and other Java EE component classes supporting injection. The resulting instance may or may not be a contextual instance as defined by Section 6.5.2, “Contextual instance of a bean”.

The container is required to perform dependency injection whenever it creates one of the following contextual objects:

  • contextual instances of session beans, and

  • contextual instances of managed beans.

The container is also required to perform dependency injection whenever it instantiates any of the following non-contextual objects:

  • non-contextual instances of session beans (for example, session beans obtained by the application from JNDI or injected using @EJB),

  • non-contextual instances of managed beans, and

  • instances of any other Java EE component class supporting injection.

A Java EE 5 container is not required to support injection for non-contextual objects.

The container interacts with instances of beans and other Java EE component classes supporting injection by calling methods and getting and setting field values.

The object injected by the container may not be a direct reference to a contextual instance of the bean. Instead, it is an injectable reference, as defined by Section 6.5.5, “Injectable references”.

5.5.1. Injection using the bean constructor

When the container instantiates a managed bean or session bean with a constructor annotated @Inject, the container calls this constructor, passing an injectable reference to each parameter. If there is no constructor annotated @Inject, the container calls the constructor with no parameters.

5.5.2. Injection of fields and initializer methods

When the container creates a new instance of a managed bean, session bean, or of any other Java EE component class supporting injection, the container must:

  • Initialize the values of all injected fields. The container sets the value of each injected field to an injectable reference.

  • Call all initializer methods, passing an injectable reference to each parameter.

The container must ensure that:

  • Initializer methods declared by a class X in the type hierarchy of the bean are called after all injected fields declared by X or by superclasses of X have been initialized, and after all Java EE component environment resource dependencies declared by X or by superclasses of X have been injected.

  • Any @PostConstruct callback declared by a class X in the type hierarchy of the bean is called after all initializer methods declared by X or by superclasses of X have been called, after all injected fields declared by X or by superclasses of X have been initialized, and after all Java EE component environment resource dependencies declared by X or by superclasses of X have been injected.

  • Any servlet init() method is called after all initializer methods have been called, all injected fields have been initialized and all Java EE component environment resource dependencies have been injected.

5.5.3. Destruction of dependent objects

When the container destroys an instance of a bean or of any Java EE component class supporting injection, the container destroys all dependent objects, as defined in Section 6.4.2, “Destruction of objects with scope @Dependent”, after the @PreDestroy callback completes and after the servlet destroy() method is called.

5.5.4. Invocation of producer or disposer methods

When the container calls a producer or disposer method, the behavior depends upon whether the method is static or non-static:

The container passes an injectable reference to each injected method parameter. The container is also responsible for destroying dependent objects created during this invocation, as defined in Section 6.4.2, “Destruction of objects with scope @Dependent”.

5.5.5. Access to producer field values

When the container accesses the value of a producer field, the value depends upon whether the field is static or non-static:

  • If the producer field is static, the container must access the field value.

  • Otherwise, if the producer field is non-static, the container must:

5.5.6. Invocation of observer methods

When the container calls an observer method (defined in Section 10.4, “Observer methods”), the behavior depends upon whether the method is static or non-static:

  • If the observer method is static, the container must invoke the method.

  • Otherwise, if the observer method is non-static, the container must:

    • Obtain a contextual instance of the bean which declares the observer method according to Section 6.5.2, “Contextual instance of a bean”. If this observer method is a conditional observer method, obtain the contextual instance that already exists, only if the scope of the bean that declares the observer method is currently active, without creating a new contextual instance.

    • Invoke the observer method on the resulting instance, if any, as a business method invocation, as defined in Section 7.2, “Container invocations and interception”.

The container must pass the event object to the event parameter and an injectable instance to each injected method parameter. The container is also responsible for destroying dependent objects created during this invocation, as defined in Section 6.4.2, “Destruction of objects with scope @Dependent”.

5.5.7. Injection point metadata

The interface javax.enterprise.inject.spi.InjectionPoint provides access to metadata about an injection point. An instance of InjectionPoint may represent an injected field or a parameter of a bean constructor, initializer method, producer method, disposer method or observer method.

public interface InjectionPoint {
    public Type getType();
    public Set<Annotation> getQualifiers();
    public Bean<?> getBean();
    public Member getMember();
    public Annotated getAnnotated();
    public boolean isDelegate();
    public boolean isTransient();
}
  • The getBean() method returns the Bean object representing the bean that defines the injection point. If the injection point does not belong to a bean, getBean() returns a null value.

  • The getType() and getQualifiers() methods return the required type and required qualifiers of the injection point.

  • The getMember() method returns the Field object in the case of field injection, the Method object in the case of method parameter injection or the Constructor object in the case of constructor parameter injection.

  • The getAnnotated() method returns an instance of javax.enterprise.inject.spi.AnnotatedField or javax.enterprise.inject.spi.AnnotatedParameter, depending upon whether the injection point is an injected field or a constructor/method parameter.

  • The isDelegate() method returns true if the injection point is a decorator delegate injection point, and false otherwise.

  • The isTransient() method returns true if the injection point is a transient field, and false otherwise.

Occasionally, a component with scope @Dependent needs to access metadata relating to the object into which it is injected. For example, the following producer method creates injectable Loggers. The log category of a Logger depends upon the class of the object into which it is injected:

@Produces Logger createLogger(InjectionPoint injectionPoint) {
    return Logger.getLogger( injectionPoint.getMember().getDeclaringClass().getName() );    
}

The container must provide a bean with scope @Dependent, bean type InjectionPoint and qualifier @Default, allowing dependent objects, as defined in Section 6.4.1, “Dependent objects”, to obtain information about the injection point to which they belong. The built-in implementation must be a passivation capable dependency, as defined in Section 6.6.2, “Passivation capable dependencies”.

If a bean that declares any scope other than @Dependent has an injection point of type InjectionPoint and qualifier @Default, the container automatically detects the problem and treats it as a definition error.

If a Java EE component class supporting injection that is not a bean has an injection point of type InjectionPoint and qualifier @Default, the container automatically detects the problem and treats it as a definition error.

5.6. Programmatic lookup

In certain situations, injection is not the most convenient way to obtain a contextual reference. For example, it may not be used when:

  • the bean type or qualifiers vary dynamically at runtime, or

  • depending upon the deployment, there may be no bean which satisfies the type and qualifiers, or

  • we would like to iterate over all beans of a certain type.

In these situations, an instance of the javax.enterprise.inject.Instance interface may be injected:

@Inject Instance<PaymentProcessor> paymentProcessor;

The method get() returns a contextual reference:

PaymentProcessor pp = paymentProcessor.get();

Any combination of qualifiers may be specified at the injection point:

@Inject @PayBy(CHEQUE) Instance<PaymentProcessor> chequePaymentProcessor;

Or, the @Any qualifier may be used, allowing the application to specify qualifiers dynamically:

@Inject @Any Instance<PaymentProcessor> anyPaymentProcessor;
...
Annotation qualifier = synchronously ? new SynchronousQualifier() : new AsynchronousQualifier();
PaymentProcessor pp = anyPaymentProcessor.select(qualifier).get().process(payment);

In this example, the returned bean has qualifier @Synchronous or @Asynchronous depending upon the value of synchronously.

Finally, the @New qualifier may be used, allowing the application to obtain a @New qualified bean, as defined in Section 3.12, “@New qualified beans”:

@Inject @New(ChequePaymentProcessor.class) Instance<PaymentProcessor> chequePaymentProcessor;

It's even possible to iterate over a set of beans:

@Inject @Any Instance<PaymentProcessor> anyPaymentProcessor;
...
for (PaymentProcessor pp: anyPaymentProcessor) pp.test();

5.6.1. The Instance interface

The Instance interface provides a method for obtaining instances of beans with a specified combination of required type and qualifiers, and inherits the ability to iterate beans with that combination of required type and qualifiers from java.lang.Iterable:

public interface Instance<T> extends Iterable<T>, Provider<T> {
      
    public Instance<T> select(Annotation... qualifiers);
    public <U extends T> Instance<U> select(Class<U> subtype, Annotation... qualifiers);
    public <U extends T> Instance<U> select(TypeLiteral<U> subtype, Annotation... qualifiers);
    
    public boolean isUnsatisfied();
    public boolean isAmbiguous();
      
}

For an injected Instance:

  • the required type is the type parameter specified at the injection point, and

  • the required qualifiers are the qualifiers specified at the injection point.

For example, this injected Instance has required type PaymentProcessor and required qualifier @Any:

@Inject @Any Instance<PaymentProcessor> anyPaymentProcessor;

The select() method returns a child Instance for a given required type and additional required qualifiers. If no required type is given, the required type is the same as the parent.

For example, this child Instance has required type AsynchronousPaymentProcessor and additional required qualifier @Asynchronous:

Instance<AsynchronousPaymentProcessor> async = anyPaymentProcessor.select( 
            AsynchronousPaymentProcessor.class, new AsynchronousQualifier() );

If two instances of the same qualifier type are passed to select(), an IllegalArgumentException is thrown.

If an instance of an annotation that is not a qualifier type is passed to select(), an IllegalArgumentException is thrown.

The get() method must:

The iterator() method must:

The method isUnsatisfied() returns true if there is no bean that has the required type and qualifiers and is eligible for injection into the class into which the parent Instance was injected, or false otherwise.

The method isAmbiguous() returns true if there is more than one bean that has the required type and qualifiers and is eligible for injection into the class into which the parent Instance was injected, or false otherwise.

5.6.2. The built-in Instance

The container must provide a built-in bean with:

  • Instance<X> and Provider<X> for every legal bean type X in its set of bean types,

  • every qualifier type in its set of qualifier types,

  • scope @Dependent,

  • no bean EL name, and

  • an implementation provided automatically by the container.

The built-in implementation must be a passivation capable dependency, as defined in Section 6.6.2, “Passivation capable dependencies”.

5.6.3. Using AnnotationLiteral and TypeLiteral

javax.enterprise.util.AnnotationLiteral makes it easier to specify qualifiers when calling select():

public PaymentProcessor getSynchronousPaymentProcessor(PaymentMethod paymentMethod) {
    
    class SynchronousQualifier extends AnnotationLiteral<Synchronous>
            implements Synchronous {}
    
    class PayByQualifier extends AnnotationLiteral<PayBy>
            implements PayBy {
        public PaymentMethod value() { return paymentMethod; }
    }
    
    return anyPaymentProcessor.select(new SynchronousQualifier(), new PayByQualifier()).get();
}

javax.enterprise.util.TypeLiteral makes it easier to specify a parameterized type with actual type parameters when calling select():

public PaymentProcessor<Cheque> getChequePaymentProcessor() {
    PaymentProcessor<Cheque> pp = anyPaymentProcessor
        .select( new TypeLiteral<PaymentProcessor<Cheque>>() {} ).get();
}