A portable extension may integrate with the container by:
-
Providing its own beans, interceptors and decorators to the container
-
Injecting dependencies into its own objects using the dependency injection service
-
Providing a context implementation for a custom scope
-
Augmenting or overriding the annotation-based metadata with metadata from some other source
The BeanAttributes
interface exposes the basic attributes of a bean.
public interface BeanAttributes<T> {
public Set<Type> getTypes();
public Set<Annotation> getQualifiers();
public Class<? extends Annotation> getScope();
public String getName();
public Set<Class<? extends Annotation>> getStereotypes();
public boolean isAlternative();
}
-
getTypes()
,getQualifiers()
,getScope()
,getName()
andgetStereotypes()
must return the bean types, qualifiers, scope type, bean name and stereotypes of the bean, as defined in [concepts]. -
isAlternative()
must returntrue
if the bean is an alternative, andfalse
otherwise.
The interface jakarta.enterprise.inject.spi.Bean
defines everything the container needs to manage instances of a certain bean.
public interface Bean<T> extends Contextual<T>, BeanAttributes<T> {
public Class<?> getBeanClass();
public Set<InjectionPoint> getInjectionPoints();
}
-
getBeanClass()
returns the bean class of the managed bean or of the bean that declares the producer method or field. -
getInjectionPoints()
returns a set ofInjectionPoint
objects, defined in [injection_point], representing injection points of the bean, that will be validated by the container at initialization time.
Note that implementations of Bean
must also implement the inherited operations defined by the Contextual
interface defined in [contextual].
An instance of Bean
must exist for every enabled bean.
A portable extension may add support for new kinds of beans beyond those defined by the this specification by implementing Bean
and registering beans with the container, using the mechanism defined in AfterBeanDiscovery
event.
Custom implementations of Bean
are encouraged to implement PassivationCapable
and may be required to in later revisions of this specification.
The Bean
object for a decorator must implement the interface jakarta.enterprise.inject.spi.Decorator
.
public interface Decorator<T> extends Bean<T> {
public Set<Type> getDecoratedTypes();
public Type getDelegateType();
public Set<Annotation> getDelegateQualifiers();
}
-
getDecoratedTypes()
returns the decorated types of the decorator. -
getDelegateType()
andgetDelegateQualifiers()
return the delegate type and qualifiers of the decorator.
An instance of Decorator
exists for every enabled decorator.
The Bean
object for an interceptor must implement jakarta.enterprise.inject.spi.Interceptor
.
public interface Interceptor<T> extends Bean<T> {
public Set<Annotation> getInterceptorBindings();
public boolean intercepts(InterceptionType type);
public Object intercept(InterceptionType type, T instance, InvocationContext ctx) throws Exception;
}
-
getInterceptorBindings()
returns the interceptor bindings of the interceptor. -
intercepts()
returnstrue
if the interceptor intercepts the specified kind of lifecycle callback or method invocation, andfalse
otherwise. -
intercept()
invokes the specified kind of lifecycle callback or method invocation interception upon the given instance of the interceptor.
An InterceptionType
identifies the kind of lifecycle callback or business method.
public enum InterceptionType {
AROUND_INVOKE, AROUND_CONSTRUCT, POST_CONSTRUCT, PRE_DESTROY, PRE_PASSIVATE, POST_ACTIVATE, AROUND_TIMEOUT
}
An instance of Interceptor
exists for every enabled interceptor.
The interface jakarta.enterprise.inject.spi.ObserverMethod
defines everything the container needs to know about an observer method.
public interface ObserverMethod<T> extends Prioritized {
public Class<?> getBeanClass();
public Type getObservedType();
public Set<Annotation> getObservedQualifiers();
public Reception getReception();
public TransactionPhase getTransactionPhase();
public int getPriority();
public void notify(T event);
public void notify(EventContext<T> eventContext);
public boolean isAsync();
}
-
getBeanClass()
returns the class of the type that declares the observer method. -
getObservedType()
andgetObservedQualifiers()
return the observed event type and qualifiers. -
getReception()
returnsIF_EXISTS
for a conditional observer andALWAYS
otherwise. -
getTransactionPhase()
returns the appropriate transaction phase for a transactional observer method orIN_PROGRESS
otherwise. -
getPriority()
this method inherited fromPrioritized
interface returns the priority that will be used by the container to determine the notification order as defined in [observer_ordering]. If this method is not implemented the default priorityAPPLICATION + 500
is assumed. -
notify()
calls the observer method, as defined in [observer_notification]. -
isAsync()
returnstrue
if the method is an asynchronous observer method otherwise returnsfalse
.
An instance of ObserverMethod
must exist for every observer method of every enabled bean.
The interface jakarta.enterprise.inject.spi.Producer
provides a generic operation for producing an instance of a type.
public interface Producer<T> {
public T produce(CreationalContext<T> ctx);
public void dispose(T instance);
public Set<InjectionPoint> getInjectionPoints();
}
For a Producer
that represents a class:
-
produce()
calls the constructor annotated@Inject
if it exists, or the constructor with no parameters otherwise, as defined in [instantiation], and returns the resulting instance. If the class has interceptors,produce()
is responsible for building the interceptors and decorators of the instance. The instance returned byproduce()
may be a proxy. -
dispose()
does nothing. -
getInjectionPoints()
returns the set ofInjectionPoint
objects representing all injected fields, bean constructor parameters and initializer method parameters.
For a Producer
that represents a producer method or field:
-
produce()
calls the producer method on, or accesses the producer field of, a contextual instance of the bean that declares the producer method, as defined in [producer_or_disposer_methods_invocation]. -
dispose()
calls the disposer method, if any, on a contextual instance of the bean that declares the disposer method, as defined in [producer_or_disposer_methods_invocation], or performs any additional required cleanup, if any, to destroy state associated with a resource. -
getInjectionPoints()
returns the set ofInjectionPoint
objects representing all parameters of the producer method.
The subinterface jakarta.enterprise.inject.spi.InjectionTarget
provides operations for performing dependency injection and lifecycle callbacks on an instance of a type.
public interface InjectionTarget<T>
extends Producer<T> {
public void inject(T instance, CreationalContext<T> ctx);
public void postConstruct(T instance);
public void preDestroy(T instance);
}
-
inject()
performs dependency injection upon the given object. The container sets the value of all injected fields, and calls all initializer methods, as defined in [fields_initializer_methods]. -
postConstruct()
calls the@PostConstruct
callback, if it exists. -
preDestroy()
calls the@PreDestroy
callback, if it exists.
Implementations of Producer
and InjectionTarget
must ensure that the set of injection points returned by getInjectionPoints()
are injected by produce()
or inject()
.
In addition to rules defined in [beancontainer], the following rules apply.
The interface jakarta.enterprise.inject.spi.BeanManager
provides operations for obtaining contextual references for beans, along with many other operations of use to applications and portable extensions.
The interface jakarta.enterprise.inject.spi.BeanManager
extends jakarta.enterprise.inject.spi.BeanContainer
.
In {cdi_full} environment, BeanContainer
is subject to the same rules as BeanManager
.
The container provides a built-in bean with bean type BeanManager
, scope @Dependent
and qualifier @Default
. The built-in implementation must be a passivation capable dependency, as defined in [passivation_capable_dependency].
Thus, any bean may obtain an instance of BeanManager
by injecting it:
@Inject BeanManager manager;
Note that, an exception is thrown if the following operations are called before the AfterBeanDiscovery
event is fired:
-
getBeans(String)
, -
getBeans(Type, Annotation…)
, -
getPassivationCapableBean(String)
-
resolve(Set)
, -
resolveDecorators(Set, Annotation…)
, -
resolveInterceptors(InterceptionType, Annotation…)
, -
resolveObserverMethods(Object, Annotation…)
, -
validate(InjectionPoint)
,
and if the following operations are called before the AfterDeploymentValidation
event is fired:
-
createInstance()
, -
getReference(Bean, Type, CreationalContext)
, -
getInjectableReference(InjectionPoint, CreationalContext)
.
All other operations of BeanManager
may be called at any time during the execution of the application.
In addition to rules defined in [provider], the following rules apply.
Portable extensions and other objects sometimes interact directly with the container via programmatic API call.
The abstract jakarta.enterprise.inject.spi.CDI
provides access to the BeanManager
as well providing lookup of bean instances.
A portable extension or other object may obtain a reference to the current container by calling CDI.current()
.
CDI.getBeanManager()
and CDI.getBeanContainer()
may be called at any time after the container fires the BeforeBeanDiscovery
container lifecycle event until the container fires the BeforeShutdown
container lifecycle event.
If methods on CDI
are called at any other time, non-portable behavior results.
In addition to rules defined in [bm_obtain_injectable_reference], the following rules apply.
If the InjectionPoint
represents a decorator delegate injection point, getInjectableReference()
returns a delegate, as defined in [delegate_attribute].
A non-contextual instance can be obtained and injected from an InjectionTarget
, however the InjectionTarget
interface is designed to work on contextual instances.
A helper class, Unmanaged
provides a set of methods optimized for working with non-contextual instances.
For example:
Unmanaged<Foo> unmanagedFoo = new Unmanaged<Foo>(Foo.class);
UnmanagedInstance<Foo> fooInstance = unmanagedFoo.newInstance();
Foo foo = fooInstance.produce().inject().postConstruct().get();
... // Use the foo instance
fooInstance.preDestroy().dispose();
In addition to rules defined in [bm_obtain_bean_by_type], the following rules apply.
The method BeanManager.getBeans()
returns the set of beans which have the given required type and qualifiers and are available for injection in the module or library containing the class into which the BeanManager
was injected or the class from whose JNDI environment namespace the BeanManager
was obtained, according to the rules for candidates of typesafe resolution defined in [performing_typesafe_resolution].
In addition to rules defined in [bm_obtain_bean_by_name], the following rules apply.
The method BeanManager.getBeans()
which accepts a string returns the set of beans which have the given bean name and are available for injection in the module or library containing the class into which the BeanManager
was injected or the class from whose JNDI environment namespace the BeanManager
was obtained, according to the rules of name resolution defined in [name_resolution].
The method BeanManager.getPassivationCapableBean()
returns the PassivationCapable
bean with the given identifier (see [passivation_capable]).
public Bean<?> getPassivationCapableBean(String id);
The BeanManager.validate()
operation validates an injection point and throws an InjectionException
if there is a deployment problem (for example, an unsatisfied or unresolvable ambiguous dependency) associated with the injection point.
public void validate(InjectionPoint injectionPoint);
The method BeanManager.resolveDecorators()
returns the ordered list of decorators for a set of bean types and a set of qualifiers and which are enabled in the module or library containing the class into which the BeanManager
was injected or the class from whose JNDI environment namespace the BeanManager
was obtained, as defined in [decorator_resolution].
List<Decorator<?>> resolveDecorators(Set<Type> types, Annotation... qualifiers);
The first argument is the set of bean types of the decorated bean. The annotations are qualifiers declared by the decorated bean.
If two instances of the same non repeating qualifier type are given, an IllegalArgumentException
is thrown.
If an instance of an annotation that is not a qualifier type is given, an IllegalArgumentException
is thrown.
If the set of bean types is empty, an IllegalArgumentException
is thrown.
In addition to rules defined in [bm_interceptor_resolution], the following rules apply.
The method BeanManager.resolveInterceptors()
returns the ordered list of interceptors for a set of interceptor bindings and a type of interception and which are enabled in the module or library containing the class into which the BeanManager
was injected or the class from whose JNDI environment namespace the BeanManager
was obtained, as defined in [interceptor_resolution].
Determining if an annotation is a qualifier type, scope type, stereotype or interceptor binding type in {cdi_full}
In addition to rules defined in [bm_determining_annotation], the following rules apply.
A portable extension may test an annotation to determine if it is a qualifier type, scope type, stereotype or interceptor binding type, obtain the set of meta-annotations declared by a stereotype or interceptor binding type, or determine if a scope type is a normal or passivating scope.
public boolean isScope(Class<? extends Annotation> annotationType);
public boolean isQualifier(Class<? extends Annotation> annotationType);
public boolean isInterceptorBinding(Class<? extends Annotation> annotationType);
public boolean isStereotype(Class<? extends Annotation> annotationType);
public boolean isNormalScope(Class<? extends Annotation> scopeType);
public boolean isPassivatingScope(Class<? extends Annotation> scopeType);
public Set<Annotation> getInterceptorBindingDefinition(Class<? extends Annotation> qualifierType);
public Set<Annotation> getStereotypeDefinition(Class<? extends Annotation> stereotype);
A portable extension may determine if two qualifiers or two interceptor bindings are considered equivalent for the purposes of typesafe resolution, as defined in [performing_typesafe_resolution].
public boolean areQualifiersEquivalent(Annotation qualifier1, Annotation qualifier2);
public boolean areInterceptorBindingsEquivalent(Annotation interceptorBinding1, Annotation interceptorBinding2);
A portable extension may determine the hash code of a qualifier or interceptor binding, ignoring any members annotated with @Nonbinding
.
public int getQualifierHashCode(Annotation qualifier);
public int getInterceptorBindingHashCode(Annotation interceptorBinding);
The method BeanManager.getELResolver()
returns the jakarta.el.ELResolver
specified in [el].
public ELResolver getELResolver();
The method BeanManager.createAnnotatedType()
returns an AnnotatedType
that may be used to read the annotations of the given Java class or interface.
public <T> AnnotatedType<T> createAnnotatedType(Class<T> type);
The method BeanManager.getInjectionTargetFactory()
returns a factory capable of creating container provided implementations of InjectionTarget
for a given AnnotatedType
or throws an IllegalArgumentException
if there is a definition error associated with any injection point of the type.
public <T> InjectionTargetFactory<T> getInjectionTargetFactory(AnnotatedType<T> type);
public interface InjectionTargetFactory<T> {
public InjectionTarget<T> createInjectionTarget(Bean<T> bean);
public AnnotatedTypeConfigurator<T> configure();
}
Null should be passed to InjectionTargetFactory.createInjectionTarget()
to create a non-contextual injection target.
-
configure()
method returns anAnnotatedTypeConfigurator
as defined inAnnotatedTypeConfigurator
SPI to configure theAnnotatedType
used to create theInjectionTargetFactory
. Subsequent invocations of theconfigure()
method within oneInjectionTargetFactory
instance will always return the sameAnnotatedTypeConfigurator
instance. OncecreateInjectionTarget()
method has been invoked, any invocations ofconfigure()
throws anIllegalStateException
.
The method BeanManager.getProducerFactory()
returns a factory capable of creating container provided implementations of Producer
for a given AnnotatedMethod
or AnnotatedField
, and declaring bean, or throws an IllegalArgumentException
if there is a definition error associated with the producer method or field.
public <X> ProducerFactory<X> getProducerFactory(AnnotatedField<? super X> field, Bean<X> declaringBean);
public <X> ProducerFactory<X> getProducerFactory(AnnotatedMethod<? super X> method, Bean<X> declaringBean);
public interface ProducerFactory<X> {
public <T> Producer<T> createProducer(Bean<T> bean);
}
Null should be passed to ProducerFactory.createProducer()
to create a producer of non-contextual objects.
The method BeanManager.createInjectionPoint()
returns a container provided implementation of InjectionPoint
for a given AnnotatedField
or AnnotatedParameter
or throws an IllegalArgumentException
if there is a definition error associated with the injection point.
public InjectionPoint createInjectionPoint(AnnotatedField<?> field);
public InjectionPoint createInjectionPoint(AnnotatedParameter<?> parameter);
The method BeanManager.createBeanAttributes()
returns a container provided implementation of BeanAttributes
by reading the annotations of a given AnnotatedType
or AnnotatedMember
, according to the rules defined in [concepts], or throws an IllegalArgumentException
if there is a definition error associated with the declared bean attributes.
public <T> BeanAttributes<T> createBeanAttributes(AnnotatedType<T> type);
public BeanAttributes<?> createBeanAttributes(AnnotatedMember<?> member);
The method BeanManager.createBean()
returns a container provided implementation of Bean
. The methods accept:
-
a
BeanAttributes
, which determines the bean types, qualifiers, scope, name and stereotypes of the returnedBean
, and the return values ofisAlternative()
, and -
a class, which determines the return value of
Bean.getClass()
. -
an
InjectionTargetFactory
, which is used to obtain anInjectionTarget
. TheInjectionTarget
is used to create and destroy instances of the bean, to perform dependency injection and lifecycle callbacks, and which determines the return value ofBean.getInjectionPoints()
.
public <T> Bean<T> createBean(BeanAttributes<T> attributes, Class<T> beanClass,
InjectionTargetFactory<T> injectionTargetFactory);
A second version of the method is provided to create a Bean
from a producer.
The method accepts:
-
a
BeanAttributes
, which determines the bean types, qualifiers, scope, name and stereotypes of the returnedBean
, and the return values ofisAlternative()
, and -
a class, which determines the return value of
Bean.getClass()
. -
a
ProducerFactory
, which is used to obtain aProducer
. TheProducer
is used to create and destroy instances of the bean, and which determines the return value ofBean.getInjectionPoints()
.
public <T, X> Bean<T> createBean(BeanAttributes<T> attributes, Class<X> beanClass,
ProducerFactory<X> producer);
The method BeanManager.getExtension()
returns the container’s instance of an Extension
class declared in META-INF/services
, or throws an IllegalArgumentException
if the container has no instance of the given class.
public <T extends Extension> T getExtension(Class<T> extensionClass);
The method BeanManager.getInterceptionFactory()
returns an InterceptionFactory
for the provided type as defined in The InterceptionFactory
interface.
<T> InterceptionFactory<T> createInterceptionFactory(CreationalContext<T> ctx, Class<T> clazz);
If the actual type parameter of the method is not a Java class, non-portable behavior results.
In addition to rules defined in [bm_obtain_instance], the following rules apply.
The returned Instance
object can only access instances of beans that are available for injection in the module or library containing the class into which the BeanManager
was injected or the Jakarta EE component from whose JNDI environment namespace the BeanManager
was obtained, according to the rules defined in [typesafe_resolution].
A portable extension may provide an alternative metadata source, such as configuration by XML.
The interfaces AnnotatedType
, AnnotatedField
, AnnotatedMethod
, AnnotatedConstructor
and AnnotatedParameter
in the package jakarta.enterprise.inject.spi
allow a portable extension to specify metadata that overrides the annotations that exist on a bean class.
The portable extension is responsible for implementing the interfaces, thereby exposing the metadata to the container.
In general, the behavior is as defined by the Java Language Specification, and only deviations from the Java Language Specification are noted.
The interface jakarta.enterprise.inject.spi.AnnotatedType
exposes the Class
object and members.
public interface AnnotatedType<X>
extends Annotated {
public Class<X> getJavaClass();
public Set<AnnotatedConstructor<X>> getConstructors();
public Set<AnnotatedMethod<? super X>> getMethods();
public Set<AnnotatedField<? super X>> getFields();
}
-
getConstructors()
returns all default-access, public, protected or private constructors declared for the type. -
getMethods()
returns all default-access, public, protected or private methods declared on the type and those declared on any supertypes. The container should callAnnotatedMethod.getJavaMember().getDeclaringClass()
to determine the type in the type hierarchy that declared the method. -
getFields()
returns all default-access, public, protected or private fields declared on the type and those declared on any supertypes. The container should callAnnotatedField.getJavaMember().getDeclaringClass()
to determine the type in the type hierarchy that declared the field.
When determining annotations on a type, the container must only consider the special inheritance rules defined for scope types in [type_level_inheritance].
The interface jakarta.enterprise.inject.spi.AnnotatedField
exposes the Field
object.
public interface AnnotatedField<X>
extends AnnotatedMember<X> {
public Field getJavaMember();
}
The interface jakarta.enterprise.inject.spi.AnnotatedMethod
exposes the Method
object.
public interface AnnotatedMethod<X>
extends AnnotatedCallable<X> {
public Method getJavaMember();
}
The interface jakarta.enterprise.inject.spi.AnnotatedConstructor
exposes the Constructor
object.
public interface AnnotatedConstructor<X>
extends AnnotatedCallable<X> {
public Constructor<X> getJavaMember();
}
The interface jakarta.enterprise.inject.spi.AnnotatedParameter
exposes the position
of the parameter object and the declaring program element.
public interface AnnotatedParameter<X>
extends Annotated {
public int getPosition();
public AnnotatedCallable<X> getDeclaringCallable();
}
The interface jakarta.enterprise.inject.spi.AnnotatedMember
exposes the Member
object and the AnnotatedType
that defines the member.
public interface AnnotatedMember<X>
extends Annotated {
public Member getJavaMember();
public boolean isStatic();
public AnnotatedType<X> getDeclaringType();
}
The interface jakarta.enterprise.inject.spi.AnnotatedCallable
exposes the parameters of an invokable object.
CDI 1.1 deprecated the method AnnotatedMember.isStatic()
. The container should instead call AnnotatedMember.getJavaMember().getModifiers()
to determine if the member is static.
public interface AnnotatedCallable<X>
extends AnnotatedMember<X> {
public List<AnnotatedParameter<X>> getParameters();
}
The interface jakarta.enterprise.inject.spi.Annotated
exposes the overriding annotations and type declarations.
public interface Annotated {
Type getBaseType();
Set<Type> getTypeClosure();
<T extends Annotation> T getAnnotation(Class<T> annotationType);
<T extends Annotation> Set<T> getAnnotations(Class<T> annotationType);
Set<Annotation> getAnnotations();
boolean isAnnotationPresent(Class<? extends Annotation> annotationType);
}
-
getBaseType()
returns the type of the program element. -
getTypeClosure()
returns all types to which the base type should be considered assignable. -
getAnnotation(Class<T>)
returns the program element annotation of the given annotation type, or a null value. -
getAnnotations(Class<T>)
returns the program element annotations of the given annotation type, or an empty set. -
getAnnotations()
returns all annotations of the program element. -
isAnnotationPresent(Class<T>)
returnstrue
if the program element has an annotation of the given annotation type, orfalse
otherwise.
The container must use the operations of Annotated
and its subinterfaces to discover program element types and annotations.
The container must not directly call the Java Reflection API. In particular, the container must:
-
call
Annotated.getBaseType()
to determine the type of an injection point, event parameter or disposed parameter, -
call
Annotated.getTypeClosure()
to determine the bean types of any kind of bean, -
call
Annotated.getAnnotations()
to determine the scope, qualifiers, stereotypes and interceptor bindings of a bean, -
call
Annotated.isAnnotationPresent()
andAnnotated.getAnnotation()
to read any bean annotations defined by this specification, and -
call
AnnotatedType.getConstructors()
,AnnotatedType.getMethods()
andAnnotatedType.getFields()
to determine the members of a bean class.
CDI 2.0 introduced a new SPI to help defining and creating instance for type metadata.
This SPI is composed of the following interfaces:
-
jakarta.enterprise.inject.spi.configurator.AnnotatedTypeConfigurator
to configure anAnnotatedType
-
jakarta.enterprise.inject.spi.configurator.AnnotatedFieldConfigurator
(defined inAnnotatedFieldConfigurator
) to configure anAnnotatedField
-
jakarta.enterprise.inject.spi.configurator.AnnotatedConstructorConfigurator
(defined inAnnotatedConstructorConfigurator
) to configure anAnnotatedConstructor
-
jakarta.enterprise.inject.spi.configurator.AnnotatedMethodConfigurator
(defined inAnnotatedMethodConfigurator
) to configure anAnnotatedMethod
-
jakarta.enterprise.inject.spi.configurator.AnnotatedParameterConfigurator
(defined inAnnotatedParameterConfigurator
) to configure anAnnotatedParameter
The container must provide an implementation for each of these interfaces.
AnnotatedTypeConfigurator
is the entry point for this SPI.
Implementation of AnnotatedTypeConfigurator
is returned by methods in the following lifecycle event:
-
BeforeBeanDiscovery
as defined inBeforeBeanDiscovery
event -
ProcessAnnotatedType
as defined inProcessAnnotatedType
event -
AfterTypeDiscovery
as defined inAfterTypeDiscovery
event
public interface AnnotatedTypeConfigurator<T> {
AnnotatedType<T> getAnnotated();
AnnotatedTypeConfigurator<T> add(Annotation annotation);
AnnotatedTypeConfigurator<T> remove(Predicate<Annotation> predicate);
AnnotatedTypeConfigurator<T> removeAll();
Set<AnnotatedMethodConfigurator<T>> methods();
Stream<AnnotatedMethodConfigurator<T>> filterMethods(Predicate<AnnotatedMethod<T>> predicate);
Set<AnnotatedFieldConfigurator<T>> fields();
Stream<AnnotatedFieldConfigurator<T>> filterFields(Predicate<AnnotatedField<T>> predicate);
Set<AnnotatedConstructorConfigurator<T>> constructors();
Stream<AnnotatedConstructorConfigurator<T>> filterConstructors(Predicate<AnnotatedConstructor<T>> predicate);
}
-
getAnnotated()
returns the originalAnnotatedType
with which this configurator was initialized -
add()
adds an annotation to the configured element -
remove()
removes annotations that match the specified predicate from the configured element -
removeAll()
removes all annotations from the configured element -
methods()
returns a set ofAnnotatedMethodConfigurator
to configure annotations on methods -
filterMethods()
returns aStream<AnnotatedMethodsConfigurator>
filtered by applying the provided Predicate onmethods()
-
fields()
returns a set ofAnnotatedFieldConfigurator
to configure annotations on fields -
filterFields()
returns aStream<AnnotatedFieldConfigurator>
filtered by applying the provided Predicate onfields()
-
constructors()
returns a set ofAnnotatedConstructorConfigurator
to configure annotations on constructors -
filterConstructors()
returns aStream<AnnotatedConstructorConfigurator>
filtered by applying the provided Predicate onConstructors()
AnnotatedMethodConfigurator
is obtained through AnnotatedTypeConfigurator
as defined in AnnotatedTypeConfigurator
SPI
public interface AnnotatedMethodConfigurator<T> {
AnnotatedMethod<T> getAnnotated();
AnnotatedMethodConfigurator<T> add(Annotation annotation);
AnnotatedMethodConfigurator<T> remove(Predicate<Annotation> predicate);
AnnotatedMethodConfigurator<T> removeAll();
List<AnnotatedParameterConfigurator<T>> params();
Stream<AnnotatedParameterConfigurator<T>> filterParams(Predicate<AnnotatedParameter<T>> predicate);
}
-
getAnnotated()
returns the originalAnnotatedMethod
with which this configurator was initialized -
add()
adds an annotation to the configured element -
remove()
removes annotations that match the specified predicate from the configured element -
removeAll()
removes all annotations from the configured element -
params()
returns a list ofAnnotatedParameterConfigurator
to configure annotations on parameters. -
filterParams(Predicate<AnnotatedParameter<T>> predicate)
returns aStream<AnnotatedParameterConfigurator>
filtered by applying the provided Predicate onparams()
AnnotatedConstructorConfigurator
is obtained through AnnotatedTypeConfigurator
as defined in AnnotatedTypeConfigurator
SPI
public interface AnnotatedConstructorConfigurator<T> {
AnnotatedConstructor<T> getAnnotated();
AnnotatedConstructorConfigurator<T> add(Annotation annotation);
AnnotatedConstructorConfigurator<T> remove(Predicate<Annotation> predicate);
AnnotatedConstructorConfigurator<T> removeAll();
List<AnnotatedParameterConfigurator<T>> params();
Stream<AnnotatedParameterConfigurator<T>> filterParams(Predicate<AnnotatedParameter<T>> predicate);
}
-
getAnnotated()
returns the originalAnnotatedConstructor
with which this configurator was initialized -
add()
adds an annotation to the configured element -
remove()
removes annotations that match the specified predicate from the configured element -
removeAll()
removes all annotations from the configured element -
params()
returns a list ofAnnotatedParameterConfigurator
to configure annotations on parameters. -
filterParams(Predicate<AnnotatedParameter<T>> predicate)
returns aStream<AnnotatedParameterConfigurator>
filtered by applying the provided Predicate onparams()
AnnotatedParameterConfigurator
is obtained through AnnotatedMethodConfigurator
(as defined in AnnotatedMethodConfigurator
) and AnnotatedConstructorConfigurator
as defined in AnnotatedConstructorConfigurator
.
public interface AnnotatedParameterConfigurator<T> {
AnnotatedParameter<T> getAnnotated();
AnnotatedParameterConfigurator<T> add(Annotation annotation);
AnnotatedParameterConfigurator<T> remove(Predicate<Annotation> predicate);
AnnotatedParameterConfigurator<T> removeAll();
}
-
getAnnotated()
returns the originalAnnotatedParameter
with which this configurator was initialized -
add()
adds an annotation to the configured element -
remove()
removes annotations that match the specified predicate from the configured element -
removeAll()
removes all annotations from the configured element
AnnotatedFieldConfigurator
is obtained through AnnotatedTypeConfigurator
as defined in AnnotatedTypeConfigurator
SPI:
public interface AnnotatedFieldConfigurator<T> {
AnnotatedField<T> getAnnotated();
AnnotatedFieldConfigurator<T> add(Annotation annotation);
AnnotatedFieldConfigurator<T> remove(Predicate<Annotation> predicate);
AnnotatedFieldConfigurator<T> removeAll();
}
-
getAnnotated()
returns the originalAnnotatedField
with which this configurator was initialized -
add()
adds an annotation to the configured element -
remove()
removes annotations that match the specified predicate from the configured element -
removeAll()
removes all annotations from the configured element
During the application initialization process, the container fires a series of events, allowing portable extensions to integrate with the container initialization process defined in [initialization]. These events are fired synchronously.
Observer methods of these events must belong to extensions.
An extension is a service provider of the service jakarta.enterprise.inject.spi.Extension
declared in META-INF/services
.
public interface Extension {}
If any method on the event object is called outside of the observer method invocation, an IllegalStateException
is thrown.
Service providers may have observer methods, which may observe any event, including any container lifecycle event, and obtain an injected BeanManager
reference. Any decorators associated with BeanManager
will not be applied.
If other beans are injected into an extension’s observer methods, non-portable behavior results.
An extension may use BeanManager.getEvent()
to deliver events to observer methods defined on extensions.
The container is not required to deliver events fired during application initialization to observer methods defined on beans.
The container instantiates a single instance of each extension at the beginning of the application initialization process and maintains a reference to it until the application shuts down. The container delivers event notifications to this instance by calling its observer methods.
If an extension declares a static observer method whose event parameter type:
-
is a container lifecycle event, or
-
is
java.lang.Object
and the event parameter has either no qualifiers or a single qualifier@Any
,
non-portable behavior results.
The notification order for observer methods within extensions follows the same ordering rule as defined in [observer_ordering] for non-extension observers.
The priority of an observer method may be declared using the @Priority
annotation.
void beforeBeanDiscovery(@Observes @Priority(jakarta.interceptor.Interceptor.Priority.LIBRARY_BEFORE) BeforeBeanDiscovery event) { ... }
For each service provider, the container must provide a bean of scope @ApplicationScoped
and qualifier @Default
, supporting injection of a reference to the service provider instance. The bean types of this bean include the class of the service provider and all superclasses and interfaces.
Lifecycle events described below can be grouped into two categories:
-
Application lifecycle events, that are fired once:
-
BeforeBeanDiscovery
-
AfterTypeDiscovery
-
AfterBeanDiscovery
-
AfterDeploymentValidation
-
BeforeShutdown
-
-
Bean discovery events, that are fired multiple times:
-
ProcessAnnotatedType
-
ProcessInjectionPoint
-
ProcessInjectionTarget
-
ProcessBeanAttributes
-
ProcessBean
-
ProcessProducer
-
ProcessObserverMethod
-
Note that the chronological order of these events is specified in [initialization].
The container must fire an event before it begins the type discovery process.
The event object must be of type jakarta.enterprise.inject.spi.BeforeBeanDiscovery
:
public interface BeforeBeanDiscovery {
public void addQualifier(Class<? extends Annotation> qualifier);
public void addQualifier(AnnotatedType<? extends Annotation> qualifier);
public void addScope(Class<? extends Annotation> scopeType, boolean normal, boolean passivating);
public void addStereotype(Class<? extends Annotation> stereotype, Annotation... stereotypeDef);
public void addInterceptorBinding(Class<? extends Annotation> bindingType, Annotation... bindingTypeDef);
public void addInterceptorBinding(AnnotatedType<? extends Annotation> bindingType);
public void addAnnotatedType(AnnotatedType<?> type, String id);
public AnnotatedTypeConfigurator<?> addAnnotatedType(Class<T> type,String id);
<T extends Annotation> AnnotatedTypeConfigurator<T> configureQualifier(Class<T> qualifier);
<T extends Annotation> AnnotatedTypeConfigurator<T> configureInterceptorBinding(Class<T> bindingType);
}
-
addQualifier()
declares an annotation type as a qualifier type. -
addScope()
declares an annotation type as a scope type. -
addStereotype()
declares an annotation type as a stereotype, and specifies its meta-annotations. -
addInterceptorBinding()
declares an annotation type as an interceptor binding type, and specifies its meta-annotations. -
addAnnotatedType()
adds a givenAnnotatedType
to the set of types which will be scanned during bean discovery, with an optional identifier.Second version of the method returns a new
AnnotatedTypeConfigurator
as defined inAnnotatedTypeConfigurator
SPI to easily configure theAnnotatedType
which will be added at the end of the observer invocation. The returnedAnnotatedTypeConfigurator
is initialized with type and annotations of the provided class. -
configureQualifier()
returns a newAnnotatedTypeConfigurator
as defined inAnnotatedTypeConfigurator
SPI to configure a newAnnotatedType
and declares it as a qualifier type. -
configureInterceptorBinding()
returns a newAnnotatedTypeConfigurator
as defined inAnnotatedTypeConfigurator
SPI to configure a newAnnotatedType
and declares it as an interceptor binding.
void beforeBeanDiscovery(@Observes BeforeBeanDiscovery event) { ... }
If any observer method of the BeforeBeanDiscovery
event throws an exception, the exception is treated as a definition error by the container.
If any BeforeBeanDiscovery
method is called outside of the observer method invocation, an IllegalStateException
is thrown.
The container must fire an event when it has fully completed the type discovery process and before it begins the bean discovery process.
The event object must be of type jakarta.enterprise.inject.spi.AfterTypeDiscovery
.
public interface AfterTypeDiscovery {
public List<Class<?>> getAlternatives();
public List<Class<?>> getInterceptors();
public List<Class<?>> getDecorators();
public void addAnnotatedType(AnnotatedType<?> type, String id);
public AnnotatedTypeConfigurator<?> addAnnotatedType(Class<T> type,String id);
}
-
getAlternatives()
returns the ordered list of enabled alternatives for the application, sorted by priority in ascending order. Alternatives enabled for a bean archive are not included in the list. -
getInterceptors()
returns the ordered list of enabled interceptors for the application, sorted by priority in ascending order. Interceptors enabled for a bean archive are not included in the list. -
getDecorators()
returns the ordered list of enabled decorators for the application, sorted by priority in ascending order. Decorators enabled for a bean archive are not included in the list. -
addAnnotatedType()
adds a givenAnnotatedType
to the set of types which will be scanned during bean discovery, with an identifier.The second version of the method, returns a new
AnnotatedTypeConfigurator
as defined inAnnotatedTypeConfigurator
SPI to easily configure theAnnotatedType
which will be added at the end of observer invocation. The returnedAnnotatedTypeConfigurator
is initialized with type and annotations of the provided class.
If an alternative, interceptor or decorator is added using AfterTypeDiscovery.addAnnotatedType()
, non-portable behavior results.
Any observer of this event is permitted to add classes to, or remove classes from, the list of alternatives, list of interceptors or list of decorators.
The container must use the final values of these collections, after all observers of AfterTypeDiscovery
have been called, to determine the order of the enabled alternatives, interceptors, and decorators for application.
The initial values of these collections are defined by the @Priority
annotation.
void afterTypeDiscovery(@Observes AfterTypeDiscovery event) { ... }
If any observer method of a AfterTypeDiscovery
event throws an exception, the exception is treated as a definition error by the container.
If any AfterTypeDiscovery
method is called outside of the observer method invocation, an IllegalStateException
is thrown.
The container must fire an event when it has fully completed the bean discovery process, validated that there are no definition errors relating to the discovered beans, and registered Bean
and ObserverMethod
objects for the discovered beans.
The event object must be of type jakarta.enterprise.inject.spi.AfterBeanDiscovery
:
public interface AfterBeanDiscovery {
public void addDefinitionError(Throwable t);
public void addBean(Bean<?> bean);
public BeanConfigurator<?> addBean();
public void addObserverMethod(ObserverMethod<?> observerMethod);
public ObserverMethodConfigurator<?> addObserverMethod();
public void addContext(Context context);
public <T> AnnotatedType<T> getAnnotatedType(Class<T> type, String id);
public <T> Iterable<AnnotatedType<T>> getAnnotatedTypes(Class<T> type);
}
-
addDefinitionError()
registers a definition error with the container, causing the container to abort deployment after all observers have been notified. -
addBean()
fires an event of typeProcessSyntheticBean
containing the givenBean
and then registers theBean
with the container, thereby making it available for injection into other beans. The givenBean
may implementInterceptor
orDecorator
.The second version of the method, returns a new
BeanConfigurator
as defined inBeanConfigurator
interface to easily configure theBean
which will be added at the end of observer invocation. If the container is unable to process the configurator it automatically detects the problem and treats it as a deployment problem. -
addObserverMethod()
fires an event of typeProcessSyntheticObserverMethod
containing the givenObserverMethod
and then registers theObserverMethod
with the container, thereby making it available for event notifications.If the given
ObserverMethod
does not override eitherObserverMethod.notify(T)
orObserverMethod.notify(EventContext<T>)
, the container automatically detects the problem and treats it as a definition error.The second version of the method, returns a new
ObserverMethodConfigurator
as defined inObserverMethodConfigurator
interface to easily configure theObserverMethod
which will be added at the end of observer invocation. If the container is unable to process the configurator it automatically detects the problem and treats it as a deployment problem. -
addContext()
registers a customContext
object with the container. -
getAnnotatedType()
andgetAnnotatedTypes()
returns theAnnotatedType
s discovered or added during container initialization. The id of anAnnotatedType
added by the container is not defined. If theid
passed is null, the container should substitute the container generated id.
A portable extension may take advantage of this event to register beans, interceptors, decorators, observer methods and custom context objects with the container.
void afterBeanDiscovery(@Observes AfterBeanDiscovery event, BeanManager manager) { ... }
If any observer method of the AfterBeanDiscovery
event throws an exception, the exception is treated as a definition error by the container.
If any AfterBeanDiscovery
method is called outside of the observer method invocation, an IllegalStateException
is thrown.
CDI 2.0 introduced the jakarta.enterprise.inject.spi.configurator.BeanConfigurator
interface to help configuring a new Bean
instance.
With BeanConfigurator
you can perform all the operations defined in BeanAttributesConfigurator
interface plus the following:
-
Initialize the bean metadata with one of its
read()
methods. It can be done from an existingBeanAttributes
or by reading metadata on a givenAnnotatedType
, according to the rules defined in [concepts]. -
Set the class of the bean with
beanClass
method. -
Add an injection point for the bean with
addInjectionPoint
method. -
Add multiple injection points for the bean with
addInjectionPoints
methods. -
Replace all injection points for the bean with
injectionPoints
methods. -
Make the bean implements
PassivationCapable
and set its id withid
method. -
Set a callback to create a bean instance with
createWith()
orproduceWith()
method. -
Set a callback to destroy a bean instance with
destroyWith()
ordisposeWith()
method.
If a BeanConfigurator
has no scope specified, the default scope rules, defined in [default_scope], apply.
CDI 2.0 introduced the jakarta.enterprise.inject.spi.configurator.ObserverMethodConfigurator
interface to help configuring an ObserverMethod
instance.
With ObserverMethodConfigurator
you can perform the following operations:
-
Read the observer metadata from a
java.lang.reflect.Method
,AnnotatedMethod
or an existingObserverMethod
with one of itsread()
methods. -
Set the
ObserverMethod
bean class withbeanClass
method. -
Set the type of the observed event with
observedType
method. -
Add a qualifier with
addQualifier
method. -
Set or add multiple qualifiers with
addQualifiers
andqualifiers
methods. -
Set the
Reception
type with reception method. -
Set the
TransactionPhase
type withtransactionPhase
method. -
Set the priority with
priority
method. -
Define the
EventConsumer
to call on notification withnotifyWith
method. -
Make the observer asynchronous with
async
method.
The container must fire an event after it has validated that there are no deployment problems and before creating contexts or processing requests.
The event object must be of type jakarta.enterprise.inject.spi.AfterDeploymentValidation
:
public interface AfterDeploymentValidation {
public void addDeploymentProblem(Throwable t);
}
-
addDeploymentProblem()
registers a deployment problem with the container, causing the container to abort deployment after all observers have been notified.
void afterDeploymentValidation(@Observes AfterDeploymentValidation event, BeanManager manager) { ... }
If any observer method of the AfterDeploymentValidation
event throws an exception, the exception is treated as a deployment problem by the container.
If any AfterDeploymentValidation
method is called outside of the observer method invocation, an IllegalStateException
is thrown.
The container must not allow any request to be processed by the deployment until all observers of this event return.
The container must fire a final event after it has finished processing requests and destroyed all contexts.
The event object must be of type jakarta.enterprise.inject.spi.BeforeShutdown
:
public interface BeforeShutdown {}
void beforeShutdown(@Observes BeforeShutdown event, BeanManager manager) { ... }
If any observer method of the BeforeShutdown
event throws an exception, the exception is ignored by the container.
The container must fire an event, before it processes a type, for every Java class, interface (excluding annotation type, a special kind of interface type) or enum discovered as defined in [type_discovery_steps].
An event is not fired for any type annotated with @Vetoed
, or in a package annotated with @Vetoed
.
The event object must be of type jakarta.enterprise.inject.spi.ProcessAnnotatedType<X>
, where X
is the class, for types discovered in a bean archive, or of type jakarta.enterprise.inject.spi.ProcessSyntheticAnnotatedType<X>
for types added by BeforeBeanDiscovery.addAnnotatedType()
or AfterTypeDiscovery.addAnnotatedType()
.
The annotation @WithAnnotations
may be applied to the event parameter.
If the annotation is applied, the container must only deliver ProcessAnnotatedType
events for types which contain at least one of the annotations specified.
The annotation can appear on the annotated type, or on any member, or any parameter of any member of the annotated type, as defined in Alternative metadata sources.
The annotation may be applied as a meta-annotation on any annotation considered.
If the @WithAnnotations
annotation is applied to any other event parameter, the container automatically detects the problem and treats it as a definition error.
public interface ProcessAnnotatedType<X> {
public AnnotatedType<X> getAnnotatedType();
public void setAnnotatedType(AnnotatedType<X> type);
public AnnotatedTypeConfigurator<X> configureAnnotatedType();
public void veto();
}
interface ProcessSyntheticAnnotatedType<X> extends ProcessAnnotatedType<X> {
public Extension getSource();
}
-
getAnnotatedType()
returns theAnnotatedType
object that will be used by the container to read the declared annotations. -
setAnnotatedType()
replaces theAnnotatedType
. -
configureAnnotatedType()
returns anAnnotatedTypeConfigurator
(as defined inAnnotatedTypeConfigurator
SPI) initialized with theAnnotatedType
processed by the event to easily configure theAnnotatedType
which will be used to replace the original one at the end of observer invocation. The method always returns the sameAnnotatedTypeConfigurator
-
veto()
forces the container to ignore the type. -
getSource()
returns theExtension
instance that added the annotated type.
Any observer of this event is permitted to wrap and/or replace the AnnotatedType
by calling either setAnnotatedType()
or configureAnnotatedType()
.
If both methods are called within an observer notification an IllegalStateException
is thrown.
The container must use the final value of this property, after all observers have been called, as the only source of types and annotations for the program elements.
For example, the following observer decorates the AnnotatedType
for every class that is discovered by the container.
<T> void decorateAnnotatedType(@Observes ProcessAnnotatedType<T> pat) {
pat.setAnnotatedType( decorate( pat.getAnnotatedType() ) );
}
If any observer method of a ProcessAnnotatedType
event throws an exception, the exception is treated as a definition error by the container.
If any ProcessAnnotatedType
method is called outside of the observer method invocation, an IllegalStateException
is thrown.
The container must fire an event for every injection point of every bean, interceptor or decorator.
The event object must be of type jakarta.enterprise.inject.spi.ProcessInjectionPoint<T, X>
where T
is the bean class, and X
is the declared type of the injection point.
public interface ProcessInjectionPoint<T, X> {
public InjectionPoint getInjectionPoint();
public void setInjectionPoint(InjectionPoint injectionPoint);
public InjectionPointConfigurator configureInjectionPoint();
public void addDefinitionError(Throwable t);
}
-
getInjectionPoint()
returns theInjectionPoint
object that will be used by the container to perform injection. -
setInjectionPoint()
replaces theInjectionPoint
. -
configureInjectionPoint()
returns anInjectionPointConfigurator
(as defined inInjectionPointConfigurator
interface) initialized with theInjectionPoint
processed by the event to easily configure theInjectionPoint
which will be used to replace the original one at the end of observer invocation. The method always returns the sameInjectionPointConfigurator
. -
addDefinitionError()
registers a definition error with the container, causing the container to abort deployment after bean discovery is complete.
Any observer of this event is permitted to wrap and/or replace the InjectionPoint
by calling either setInjectionPoint()
or configureInjectionPoint()
.
If both methods are called within an observer notification an IllegalStateException
is thrown.
The container must use the final value of this property, after all observers have been called, whenever it performs injection upon the injection point.
If any observer method of a ProcessInjectionPoint
event throws an exception, the exception is treated as a definition error by the container.
If any ProcessInjectionPoint
method is called outside of the observer method invocation, an IllegalStateException
is thrown.
CDI 2.0 introduced the jakarta.enterprise.inject.spi.configurator.InjectionPointConfigurator
interface to help configure an existing InjectionPoint
instance.
With InjectionPointConfigurator
you can perform the following operations:
-
Set the type of
InjectionPoint
withtype
method. -
Add a qualifier with
addQualifier
method. -
Set or add multiple qualifiers with
addQualifiers
andqualifiers
methods. -
Make the injection point delegate with
delegate
method. -
Make the injection point a transient field with
transientField
method.
The container must fire an event for every bean, interceptor or decorator.
The event object must be of type jakarta.enterprise.inject.spi.ProcessInjectionTarget<X>
, where X
is the bean class.
public interface ProcessInjectionTarget<X> {
public AnnotatedType<X> getAnnotatedType();
public InjectionTarget<X> getInjectionTarget();
public void setInjectionTarget(InjectionTarget<X> injectionTarget);
public void addDefinitionError(Throwable t);
}
-
getAnnotatedType()
returns theAnnotatedType
representing the bean class. -
getInjectionTarget()
returns theInjectionTarget
object that will be used by the container to perform injection. -
setInjectionTarget()
replaces theInjectionTarget
. -
addDefinitionError()
registers a definition error with the container, causing the container to abort deployment after bean discovery is complete.
Any observer of this event is permitted to wrap and/or replace the InjectionTarget
. The container must use the final value of this property, after all observers have been called, whenever it performs injection upon the managed bean.
If any observer method of a ProcessInjectionTarget
event throws an exception, the exception is treated as a definition error by the container.
If any ProcessInjectionTarget
method is called outside of the observer method invocation, an IllegalStateException
is thrown.
The container must fire an event for each managed bean, producer, interceptor or decorator deployed in a bean archive, before registering the Bean
object.
No event is fired for any:
-
beans added programmatically using
AfterBeanDiscovery.addBean()
, or, -
for any built-in beans.
The event object must be of type jakarta.enterprise.inject.spi.ProcessBeanAttributes<T>
where T
is the bean class of the bean, the return type of the producer method, or the type of the producer field.
Resources are considered to be producer fields.
public interface ProcessBeanAttributes<T> {
public Annotated getAnnotated();
public BeanAttributes<T> getBeanAttributes();
public void setBeanAttributes(BeanAttributes<T> beanAttributes);
public BeanAttributesConfigurator<T> configureBeanAttributes();
public void addDefinitionError(Throwable t);
public void veto();
public void ignoreFinalMethods();
}
-
getAnnotated()
returns theAnnotatedType
representing the bean class, theAnnotatedMethod
representing the producer field, or theAnnotatedField
representing the producer field. -
getBeanAttributes()
returns theBeanAttributes
object that will be used by the container to manage instances of the bean. -
setBeanAttributes()
replaces theBeanAttributes
. -
configureBeanAttributes()
returns aBeanAttributesConfigurator
(as defined inBeanAttributesConfigurator
interface) initialized with theBeanAttributes
processed by the event to easily configure theBeanAttributes
which will be used to replace the original one at the end of observer invocation. The method always returns the sameBeanAttributesConfigurator
. -
addDefinitionError()
registers a definition error with the container, causing the container to abort deployment after bean discovery is complete. -
veto()
forces the container to ignore the bean. -
ignoreFinalMethods()
Instructs the container to ignore all non-static, final methods with public, protected or default visibility declared on any bean type of the specific bean during validation of injection points that require proxyable bean type. These method should never be invoked upon bean instances. Otherwise, unpredictable behavior results. It will bypass standard rules defined in [unproxyable].
Any observer of this event is permitted to wrap and/or replace the BeanAttributes
by calling either setBeanAttributes()
or configureBeanAttributes()
.
If both methods are called within an observer notification an IllegalStateException
is thrown.
The container must use the final value of this property, after all observers have been called, to manage instances of the bean.
Changes to BeanAttributes
are not propagated to the annotated type from which the bean definition was created.
Any bean which has its bean attributes altered must have it’s definition validated during deployment validation.
If any observer method of a ProcessBeanAttributes
event throws an exception, the exception is treated as a definition error by the container.
If any ProcessBeanAttributes
method is called outside of the observer method invocation, an IllegalStateException
is thrown.
CDI 2.0 introduced the jakarta.enterprise.inject.spi.configurator.BeanAttributesConfigurator
interface to help configuring a new BeanAttributes
instance.
BeanAttributesConfigurator
is obtainable during ProcessBeanAttributes
event and is therefore automatically initialized from existing BeanAttributes
.
With BeanAttributesConfigurator
you can perform the following operations :
-
Add type with
addType
oraddTransitiveTypeClosure
methods. -
Set multiple types with
types
methods. -
Set scope with
scope
method. -
Add a qualifier with
addQualifier
method. -
Set or add multiple qualifiers with
addQualifiers
andqualifiers
methods. -
Add a stereotype with
addStereotype
method. -
Set or add multiple stereotypes with
addStereotypes
andstereotypes
methods. -
Set the bean name
name
method. -
Make the bean an alternative with
alternative
methods.
The container must fire an event for each bean, interceptor or decorator deployed in a bean archive, after firing the ProcessBeanAttributes
for the bean and before registering the Bean
object.
The event object type in the package jakarta.enterprise.inject.spi
depends upon what kind of bean was discovered:
-
For a managed bean with bean class
X
, the container must raise an event of typeProcessManagedBean<X>
. -
For a producer method with method return type
T
of a bean with bean classX
, the container must raise an event of typeProcessProducerMethod<T, X>
. -
For a producer field with field type
T
of a bean with bean classX
, the container must raise an event of typeProcessProducerField<T, X>
. -
For a custom implementation of
Bean
, the container must raise an event of typeProcessSyntheticBean<X>
.
The interface jakarta.enterprise.inject.spi.ProcessBean
is a supertype of all these event types:
public interface ProcessBean<X> {
public Annotated getAnnotated();
public Bean<X> getBean();
public void addDefinitionError(Throwable t);
}
-
getAnnotated()
returns theAnnotatedType
representing the bean class, theAnnotatedMethod
representing the producer method, or theAnnotatedField
representing the producer field. If invoked upon aProcessSyntheticBean
event, non-portable behavior results and the returned value should be ignored. -
getBean()
returns theBean
object that is about to be registered. TheBean
may implementInterceptor
orDecorator
. -
addDefinitionError()
registers a definition error with the container, causing the container to abort deployment after bean discovery is complete.
public interface ProcessManagedBean<X>
extends ProcessBean<X> {
public AnnotatedType<X> getAnnotatedBeanClass();
}
public interface ProcessProducerMethod<T, X>
extends ProcessBean<X> {
public AnnotatedMethod<T> getAnnotatedProducerMethod();
public AnnotatedParameter<T> getAnnotatedDisposedParameter();
}
public interface ProcessProducerField<T, X>
extends ProcessBean<X> {
public AnnotatedField<T> getAnnotatedProducerField();
public AnnotatedParameter<T> getAnnotatedDisposedParameter();
}
public interface ProcessSyntheticBean<X>
extends ProcessBean<X> {
public Extension getSource();
}
If any observer method of a ProcessBean
event throws an exception, the exception is treated as a definition error by the container.
If any ProcessBean
method is called outside of the observer method invocation, an IllegalStateException
is thrown.
The container must fire an event for each producer method or field of each bean, including resources.
The event object must be of type jakarta.enterprise.inject.spi.ProcessProducer<T, X>
, where T
is the bean class of the bean that declares the producer method or field and X
is the return type of the producer method or the type of the producer field.
public interface ProcessProducer<T, X> {
public AnnotatedMember<T> getAnnotatedMember();
public Producer<X> getProducer();
public void setProducer(Producer<X> producer);
public ProducerConfigurator<X> configureProducer();
public void addDefinitionError(Throwable t);
}
-
getAnnotatedMember()
returns theAnnotatedField
representing the producer field or theAnnotatedMethod
representing the producer method. -
getProducer()
returns theProducer
object that will be used by the container to call the producer method or read the producer field. -
setProducer()
replaces theProducer
. -
configureProducer()
returns aProducerConfigurator
(as defined inProducerConfigurator
interface) initialized with theProducer
processed by this event to configure theProducer
that will replace the original one at the end of the observer invocation. Each call returns the same configurator instance within an observer notification. -
addDefinitionError()
registers a definition error with the container, causing the container to abort deployment after bean discovery is complete.
Any observer of this event is permitted to wrap and/or replace the Producer
by calling either setProducer()
or configureProducer()
.
If both methods are called within an observer notification an IllegalStateException
is thrown.
The container must use the final value of this property, after all observers have been called, whenever it calls the producer or disposer.
For example, this observer decorates the Producer
for all producer methods and fields of type EntityManager
.
void decorateEntityManager(@Observes ProcessProducer<?, EntityManager> pp) {
pit.setProducer( decorate( pp.getProducer() ) );
}
If any observer method of a ProcessProducer
event throws an exception, the exception is treated as a definition error by the container.
If any ProcessProducer
method is called outside of the observer method invocation, an IllegalStateException
is thrown.
CDI 2.0 introduced the jakarta.enterprise.inject.spi.configurator.ProducerConfigurator
interface to help configuring a Producer
instance.
With ProducerConfigurator
you can perform the following operations:
-
Set a callback to produce a new instance with
produceWith()
method. -
Set a callback to destroy the produced instance with
disposeWith()
method.
The container must fire an event for each observer method of each enabled bean, before registering the ObserverMethod
object.
The event object must be of type jakarta.enterprise.inject.spi.ProcessObserverMethod<T, X>
, where T
is the observed event type of the observer method and X
is the bean class of the bean that declares the observer method.
For a custom implementation of jakarta.enterprise.inject.spi.ObserverMethod
, the container must raise an event of type jakarta.enterprise.inject.spi.ProcessSyntheticObserverMethod<T, X>
, where T
is the observed event type of the observer method and X
is the return value of ObserverMethod.getBeanClass()
.
public interface ProcessObserverMethod<T, X> {
public AnnotatedMethod<X> getAnnotatedMethod();
public ObserverMethod<T> getObserverMethod();
public void addDefinitionError(Throwable t);
public void setObserverMethod(ObserverMethod<T> observerMethod);
public ObserverMethodConfigurator<T> setObserverMethod();
public void veto();
}
public interface ProcessSyntheticObserverMethod<T, X> extends ProcessObserverMethod<T, X> {
public Extension getSource();
}
-
getAnnotatedMethod()
returns theAnnotatedMethod
representing the observer method. If invoked upon aProcessSyntheticObserverMethod
event, non-portable behavior results and the returned value should be ignored. -
getObserverMethod()
returns theObserverMethod
object that will be used by the container to call the observer method. -
addDefinitionError()
registers a definition error with the container, causing the container to abort deployment after bean discovery is complete. -
setObserverMethod()
replaces theObserverMethod
. -
configureObserverMethod()
returns anObserverMethodConfigurator
(as defined inObserverMethodConfigurator
interface) initialized with theObserverMethod
processed by the event to easily configure theObserverMethod
which will be used to replace the original one at the end of observer invocation. The method always returns the sameObserverMethodConfigurator
. -
veto()
forces the container to ignore theObserverMethod
. -
getSource()
returns theExtension
instance that added the observer method.
Any observer of this event is permitted to wrap and/or replace the ObserverMethod
by calling either setObserverMethod()
or configureObserverMethod()
.
If both methods are called within an observer notification an IllegalStateException
is thrown.
The container must use the final value of this property, after all observers have been called, whenever it performs observer resolution.
If any observer method of a ProcessObserverMethod
event throws an exception, the exception is treated as a definition error by the container.
If any ProcessObserverMethod
method is called outside of the observer method invocation, an IllegalStateException
is thrown.
CDI 2.0 introduced the following Configurators interface:
-
AnnotatedTypeConfigurator
SPI forAnnotatedType
configuration -
InjectionPointConfigurator
interface forInjectionPoint
configuration -
BeanAttributesConfigurator
interface forBeanAttributes
configuration -
BeanConfigurator
interface forBean
configuration -
ObserverMethodConfigurator
interface forObserverMethod
configuration -
ProducerConfigurator
interface forProducer
configuration
The container must provide implementation for all these configurators and make them available in matching container lifecycle events as defined in Container lifecycle events.
CDI 2.0 introduces the jakarta.enterprise.inject.spi.InterceptionFactory<T>
interface, which allows to create a wrapper instance whose method invocations are intercepted by method interceptors and forwarded to a provided instance.
public interface InterceptionFactory<T> {
InterceptionFactory<T> ignoreFinalMethods();
AnnotatedTypeConfigurator<T> configure();
T createInterceptedInstance(T instance);
}
-
ignoreFinalMethods()
instructs the container to ignore all non-static, final methods with public, protected or default visibility declared by any class in the type hierarchy of the intercepted instance during invocation ofcreateInterceptedInstance()
method. Ignored methods should never be invoked upon the wrapper instance. Otherwise, unpredictable behavior results. -
configure()
returns anAnnotatedTypeConfigurator
(as defined inAnnotatedTypeConfigurator
SPI) initialized with theAnnotatedType
created either for the class passed toBeanManager.createInterceptionFactory(CreationalContext, Class)
or derived from theInterceptionFactory
parameter injection point. The method always return the sameAnnotatedTypeConfigurator
-
createInterceptedInstance()
returns a wrapper instance whose method invocations are intercepted by method interceptors and forwarded to a provided instance. The method can be only called once, subsequent calls will throw anIllegalStateException
. If the type of the instance is not proxyable as defined in [unproxyable] anUnproxyableResolutionException
exception is thrown. This rule can be loosen by callingignoreFinalMethods()
before this method. If the provided instance is an internal container construct (such as client proxy), non-portable behavior results.
An InterceptionFactory
can be obtained be calling BeanManager.createInterceptionFactory()
as defined in Obtain an InterceptionFactory
.
The container must provide a built-in bean with scope @Dependent
, bean type InterceptionFactory
and qualifier @Default
.
If an injection point of type InterceptionFactory
and qualifier @Default
exists and is not a parameter of a producer method, the container automatically detects the problem and treats it as a definition error.
If an injection point of type InterceptionFactory
has a type parameter that is not a Java class, non-portable behavior results.
The following example demonstrates a producer method definition using InterceptionFactory
. The produced bean instance will be a wrapper of Product
with single interceptor associated by ActionBinding
:
@Produces
@RequestScoped
public Product createInterceptedProduct(InterceptionFactory<Product> interceptionFactory) {
interceptionFactory.configure().add(ActionBinding.Literal.INSTANCE);
return interceptionFactory.createInterceptedInstance(new Product());
}