The container injects references to contextual instances to the following kinds of injection point:
-
Any injected field of a bean class
-
Any parameter of a bean constructor, bean initializer method, producer method or disposer method
-
Any parameter of an observer method, except for the event parameter
References to contextual instances may also be obtained by programmatic lookup.
In general, a bean type or bean name does not uniquely identify a bean. When resolving a bean at an injection point, the container considers bean type, qualifiers and selected alternatives. 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 [normal_scope]. The container is not required to support circular chains of dependencies where every bean participating in the chain has a pseudo-scope.
Beans and their clients may be deployed in modules in a module architecture. In a module architecture, certain modules are considered bean archives. The library may be an explicit bean archive or an implicit bean archive, as defined in [bean_archive]. In {cdi_lite}, libraries that are bean archives are always implicit bean archives.
A bean packaged in a certain module is available for injection, lookup and name resolution to classes 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.
An alternative is not available for injection, lookup or name resolution to classes in a module unless the module is a bean archive and the alternative is explicitly selected for the application.
{cdi_lite} defines one method of selecting alternatives: the @Priority
annotation allows an alternative to be selected for an entire application.
{cdi_full} defines an additional method of selecting alternatives, which is specified therein.
An alternative may be given a priority for the application:
-
by placing the
@Priority
annotation on the bean class of a managed bean, or -
by placing the
@Priority
annotation on the bean class that declares the producer method, field or resource.
Custom bean implementations which are also alternatives may implement Prioritized interface in which case they will be enabled for entire application with given priority.
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 either
-
it is not an alternative, or it is a selected alternative for the application.
Otherwise, the bean is said to be disabled.
A bean is available for injection in a certain module if:
-
the bean is not an interceptor
-
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 for the application, and
-
the bean class is required to be accessible to classes in the module, according to the class accessibility requirements of the module architecture.
The process of matching a bean to an injection point is called typesafe resolution. 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.
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.
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 Assignability of raw and parameterized types. -
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@jakarta.enterprise.util.Nonbinding
.
A bean is eligible for injection to a certain injection point if:
-
it is available for injection in the module that contains the class that declares the injection point, and
-
it is assignable to the injection point (using Assignability of raw and parameterized types).
For a custom implementation of the Bean
interface defined in [bean], the container calls getTypes()
and getQualifiers()
to determine the bean types and qualifiers.
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.
When an ambiguous dependency exists, the container attempts to resolve the ambiguity. The container eliminates all eligible beans that are not alternatives selected for the application, 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.
-
all the beans left are alternatives with a priority, or producer methods or fields of beans that are alternatives with a priority, then the container will determine the highest priority value, and eliminate all beans, except for alternatives with the highest priority and producer methods and fields of alternatives with the highest priority value. 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, all observer methods and all disposer methods 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 [bean], the container calls getInjectionPoints()
to determine the set of injection points.
Any legal bean type, as defined in [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.
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> { ... }
A raw bean type is considered assignable to a parameterized required type if the raw types are identical and all type parameters of the required type are either unbounded type variables or java.lang.Object
.
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.
If an injection point of primitive type resolves to a producer method or producer field that returns a null value at runtime, the container must inject the primitive type’s default value as defined by the Java Language Specification.
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.
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.
The process of matching a bean to a name is called name resolution. Since there is no typing information available during name resolution, the container may consider only the bean name. Name resolution usually occurs at runtime.
A name resolves to a bean if:
-
the bean has the given bean name, and
-
the bean is available for injection in the module where the name resolution is requested.
For a custom implementation of the Bean
interface defined in [bean], the container calls getName()
to determine the bean name.
An ambiguous name exists when a name resolves to multiple beans. When an ambiguous name exists, the container attempts to resolve the ambiguity. The container eliminates all eligible beans that are not alternatives selected for the application, 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.
-
all the beans left are alternatives with a priority, then the container will determine the highest priority value, and eliminate all beans, except for producer methods and fields of beans that are alternatives with the highest priority value. If there is exactly one bean remaining, the container will select this bean, and the ambiguous dependency is called resolvable.
All unresolvable ambiguous names are detected by the container when the application is initialized. Suppose two beans are both available for injection in a certain module, and either:
-
the two beans have the same bean name and the name is not resolvable, or
-
the bean name of one bean is of the form
x.y
, wherey
is a valid bean name, andx
is the bean name of the other bean,
the container automatically detects the problem and treats it as a deployment problem.
An injected reference, or reference obtained by programmatic lookup, is usually a contextual reference as defined by [contextual_reference].
A contextual reference to a bean with a normal scope, as defined in [normal_scope], 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 [normal_scope]) 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 [passivating_scope]. (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.)
Every time a method of the bean is invoked upon a client proxy, the client proxy must:
-
obtain a contextual instance of the bean, as defined in [contextual_instance], and
-
invoke the method upon this instance.
If the scope is not active, as specified in [active_context], 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.
From time to time the container instantiates beans and other class supporting injection. The resulting instance may or may not be a contextual instance as defined by [contextual_instance].
The container is required to perform dependency injection whenever it creates the following contextual objects:
-
contextual instances of managed beans.
The container is also required to perform dependency injection whenever it instantiates the following non-contextual objects:
-
non-contextual instances of managed beans.
The container interacts with instances of beans or objects 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 [injectable_reference].
When the container instantiates a managed 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.
When the container creates a new instance of a managed bean, 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.
-
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.
When the container destroys an instance of a bean, the container destroys all dependent objects, as defined in [dependent_destruction], after the @PreDestroy
callback completes.
When the container calls a producer or disposer method, the behavior depends upon whether the method is static or non-static:
-
If the method is static, the container must invoke the method.
-
Otherwise, if the method is non-static, the container must:
-
Obtain a contextual instance of the bean which declares the method, as defined by [contextual_instance].
-
Invoke the method upon this instance, as a business method invocation, as defined in [biz_method].
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 [dependent_destruction].
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:
-
Obtain an contextual instance of the bean which declares the producer field, as defined by [contextual_instance].
-
Access the field value of this instance.
When the container calls an observer method (defined in [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 [contextual_instance]. 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 [biz_method].
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 [dependent_destruction].
The interface jakarta.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, or
-
an instance obtained dynamically using
Instance.get()
.
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 theBean
object representing the bean that defines the injection point. If the injection point does not belong to a bean,getBean()
returns a null value. If the injection point represents a dynamically obtained instance, thegetBean()
method should return theBean
object representing the bean that defines theInstance
injection point. -
The
getType()
andgetQualifiers()
methods return the required type and required qualifiers of the injection point. If the injection point represents a dynamically obtained instance, thegetType()
andgetQualifiers()
methods should return the required type (as defined byInstance.select()
), and required qualifiers of the injection point including any additional required qualifiers (as defined byInstance.select()
). -
The
getMember()
method returns theField
object in the case of field injection, theMethod
object in the case of method parameter injection, or theConstructor
object in the case of constructor parameter injection. If the injection point represents a dynamically obtained instance, thegetMember()
method returns theField
object representing the field that defines theInstance
injection point in the case of field injection, theMethod
object representing the method that defines theInstance
injection point in the case of method parameter injection, or theConstructor
object representing the constructor that defines theInstance
injection point in the case of constructor parameter injection. -
The
getAnnotated()
method may, in {cdi_lite} environment, always returnnull
. Behavior of this method in {cdi_full} is specified therein. -
The
isDelegate()
method may, in {cdi_lite} environment, always returnfalse
. Behavior of this method in {cdi_full} is specified therein. -
The
isTransient()
method returnstrue
if the injection point is a transient field, andfalse
otherwise. If the injection point represents a dynamically obtained instance then theisTransient()
method returnstrue
if theInstance
injection point is a transient field, andfalse
otherwise. If this injection point is declared as transient, after bean’s passivation, the value will not be restored. Instance<> injection point is the preferred approach.
Occasionally, a bean with scope @Dependent
needs to access metadata relating to the object into which it is injected.
For example, the following producer method creates injectable Logger
s.
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 [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 [passivation_capable_dependency].
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 disposer method 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 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.
The interfaces Bean
and Interceptor
provide metadata about a bean.
The container must provide beans allowing a bean instance to obtain a Bean
or Interceptor
instance containing its metadata:
-
a bean with scope
@Dependent
, qualifier@Default
and typeBean
which can be injected into any bean instance -
a bean with scope
@Dependent
, qualifier@Default
and typeInterceptor
which can be injected into any interceptor instance
Additionally, the container must provide beans allowing interceptors to obtain information about the beans they intercept:
-
a bean with scope
@Dependent
, qualifier@Intercepted
and typeBean
which can be injected into any interceptor instance.
These beans are passivation capable dependencies, as defined in [passivation_capable_dependency].
If an Interceptor
instance is injected into a bean instance other than an interceptor instance, the container automatically detects the problem and treats it as a definition error.
If a Bean
instance with qualifier @Intercepted
is injected into a bean instance other than an interceptor instance, the container automatically detects the problem and treats it as a definition error.
The injection of bean metadata is restricted. If:
-
the injection point is a field, an initializer method parameter or a bean constructor, with qualifier
@Default
, then the type parameter of the injectedBean
, orInterceptor
must be the same as the type declaring the injection point, or -
the injection point is a field, an initializer method parameter or a bean constructor of an interceptor, with qualifier
@Intercepted
, then the type parameter of the injectedBean
must be an unbounded wildcard, or -
the injection point is a producer method parameter then the type parameter of the injected
Bean
must be the same as the producer method return type, or -
the injection point is a parameter of a disposer method then the container automatically detects the problem and treats it as a definition error.
Otherwise, the container automatically detects the problem and treats it as a definition error.
@Named("Order") public class OrderProcessor {
@Inject Bean<OrderProcessor> bean;
public void getBeanName() {
return bean.getName();
}
}
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 jakarta.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
.
It’s even possible to iterate over a set of beans:
@Inject @Any Instance<PaymentProcessor> anyPaymentProcessor;
...
for (PaymentProcessor pp: anyPaymentProcessor) pp.test();
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> {
Instance<T> select(Annotation... qualifiers);
<U extends T> Instance<U> select(Class<U> subtype, Annotation... qualifiers);
<U extends T> Instance<U> select(TypeLiteral<U> subtype, Annotation... qualifiers);
Stream<T> stream();
boolean isUnsatisfied();
boolean isAmbiguous();
boolean isResolvable();
void destroy(T instance);
Handle<T> getHandle();
Iterable<Handle<T>> handles();
Stream<Handle<T>> handlesStream();
}
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.
Rules specified at [injection_point_default_qualifier] are applied before performing typesafe resolution.
For example, this child Instance
has required type AsynchronousPaymentProcessor
and additional required qualifier @Asynchronous
:
Instance<AsynchronousPaymentProcessor> async = anyPaymentProcessor.select(
AsynchronousPaymentProcessor.class, new AsynchronousQualifier() );
If an injection point of raw type Instance
is defined, the container automatically detects the problem and treats it as a definition error.
If two instances of the same non repeating 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:
-
Identify a bean that has the required type and required qualifiers and is eligible for injection into the class into which the parent
Instance
was injected, according to the rules of typesafe resolution, as defined in Performing typesafe resolution, resolving ambiguities according to Unsatisfied and ambiguous dependencies. -
If typesafe resolution results in an unsatisfied dependency, throw an
UnsatisfiedResolutionException
. If typesafe resolution results in an unresolvable ambiguous dependency, throw anAmbiguousResolutionException
. -
Otherwise, obtain a contextual reference for the bean and the required type, as defined in [contextual_reference].
The iterator()
method must:
-
Identify the set of beans that have the required type and required qualifiers and are eligible for injection into the class into which the parent
Instance
was injected, according to the rules of typesafe resolution, as defined in Performing typesafe resolution, resolving ambiguities according to Unsatisfied and ambiguous dependencies. -
Return an
Iterator
, that iterates over the set of contextual references for the resulting beans and required type, as defined in [contextual_reference].
The stream()
method must:
-
Identify the set of beans that have the required type and required qualifiers and are eligible for injection into the class into which the parent
Instance
was injected, according to the rules of typesafe resolution, as defined in Performing typesafe resolution, resolving ambiguities according to Unsatisfied and ambiguous dependencies. -
Return a
Stream
, that can stream over the set of contextual references for the resulting beans and required type, as defined in [contextual_reference].
The methods isUnsatisfied()
, isAmbiguous()
and isResolvable()
must:
-
Identify the set of beans that have the required type and required qualifiers and are eligible for injection into the class into which the parent
Instance
was injected, according to the rules of typesafe resolution, as defined in Performing typesafe resolution, resolving ambiguities according to Unsatisfied and ambiguous dependencies. -
The method
isUnsatisfied()
returnstrue
if there is no bean found, orfalse
otherwise. -
The method
isAmbiguous()
returnstrue
if there is more than one bean found, orfalse
otherwise. -
The method
isResolvable()
returnstrue
if there is exactly one bean found, orfalse
otherwise.
The method destroy()
instructs the container to destroy the instance.
The bean instance passed to destroy()
should be a dependent scoped bean instance obtained from the same Instance
object, or a client proxy for a normal scoped bean.
Applications are encouraged to always call destroy()
when they no longer require an instance obtained from Instance
. All built-in normal scoped contexts support destroying bean instances.
An UnsupportedOperationException
is thrown if the active context object for the scope type of the bean does not support destroying bean instances.
The getHandle()
method must:
-
Return an initialized contextual reference
Handle<T>
for a bean that has the required type and qualifiers and is eligible for injection. The contextual reference must be resolved lazily, i.e. when first needed. TheHandle
interface is described in a separate paragraph. -
Throw
UnsatisfiedResolutionException
if there is no bean with given type and qualifiers -
Throw
AmbiguousResolutionException
if there is more than one bean given type and qualifiers
The handles()
method must:
-
Allow iterating over contextual reference handles for all beans that have the required type and required qualifiers and are eligible for injection.
-
Return stateless
Iterable
. Therefore, eachIterable#iterator()
produces a new set of handles.
The handlesStream()
is a Stream
equivalent of the aforementioned handles()
method.
Handle
is an interface representing a contextual reference handle.
It is an abstraction allowing inspection of bean metadata via Bean<?>
objects.
Handles have to resolve their contextual references lazily, i.e. when their get()
method is invoked.
Last but not least, this interface can be used to destroy the contextual instance once not needed.
public interface Handle<T> extends AutoCloseable {
T get();
Bean<T> getBean();
void destroy();
void close();
}
The get()
method returns a contextual reference object. The contextual reference is resolved lazily.
The getBean()
method returns the Bean
object representing metadata of the given contextual instance.
The destroy()
method destroys the contextual instance and is a no-op if:
-
called multiple times
-
the producing
Instance
does not exist -
the handle does not hold a contextual reference, i.e.
get()
was never called
The rules for destroying instances are the same as with Instance#destroy()
.
The close()
method delegates to the aforementioned destroy()
method.
The container must provide a built-in bean that:
-
is eligible for injection to any injection point with required type
Instance<X>
orProvider<X>
, for any legal bean typeX
, -
has any qualifiers
-
has scope
@Dependent
, -
has no bean name, and
-
has an implementation provided automatically by the container.
The built-in implementation must be a passivation capable dependency, as defined in [passivation_capable_dependency].
jakarta.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();
}
jakarta.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();
}
The following built-in annotations define a Literal
static nested class to support inline instantiation of the specific annotation type:
-
jakarta.enterprise.inject.Any
-
jakarta.enterprise.inject.Default
-
jakarta.enterprise.inject.Specializes
-
jakarta.enterprise.inject.Vetoed
-
jakarta.enterprise.util.Nonbinding
-
jakarta.enterprise.context.Initialized
-
jakarta.enterprise.context.Destroyed
-
jakarta.enterprise.context.RequestScoped
-
jakarta.enterprise.context.SessionScoped
-
jakarta.enterprise.context.ApplicationScoped
-
jakarta.enterprise.context.Dependent
-
jakarta.enterprise.context.ConversationScoped
-
jakarta.enterprise.inject.Alternative
-
jakarta.enterprise.inject.Typed
The Literal
class might be used to instantiate the matching AnnotationLiteral
:
Default defaultLiteral = new Default.Literal();
Annotations without members provide the default AnnotationLiteral
instance declared as a constant named INSTANCE
:
RequestScoped requestScopedLiteral = RequestScoped.Literal.INSTANCE;
Annotations having members do not provide the default AnnotationLiteral
instance. Instead, a constructor or factory method named of
can be used:
Initialized initializedForApplicationScoped = new Initialized.Literal(ApplicationScoped.class);
Initialized initializedForRequestScoped = Initialized.Literal.of(RequestScoped.class);
See also the annotation javadoc for more information about specific Literal
members.
In addition, CDI also provides annotation literals for the following JSR 330 annotations:
-
jakarta.inject.Inject
withjakarta.enterprise.inject.literal.InjectLiteral
class -
jakarta.inject.Named
withjakarta.enterprise.inject.literal.NamedLiteral
class -
jakarta.inject.Qualifier
withjakarta.enterprise.inject.literal.QualifierLiteral
class -
jakarta.inject.Singleton
withjakarta.enterprise.inject.literal.SingletonLiteral
class
They can be used like static nested classes described above.