[[spi_full]]

== Portable extensions

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


[[bean]]

=== The `Bean` interface

The `BeanAttributes` interface exposes the basic attributes of a bean.

[source, java]
----
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()` and `getStereotypes()` must return the bean types, qualifiers, scope type, bean name and stereotypes of the bean, as defined in <<concepts>>.
* `isAlternative()` must return `true` if the bean is an alternative, and `false` otherwise.

The interface `jakarta.enterprise.inject.spi.Bean` defines everything the container needs to manage instances of a certain bean.

[source, java]
----
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 of `InjectionPoint` 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 <<after_bean_discovery>>.

Custom implementations of `Bean` are encouraged to implement `PassivationCapable` and may be required to in later revisions of this specification.

[[decorator]]

==== The `Decorator` interface

The `Bean` object for a decorator must implement the interface `jakarta.enterprise.inject.spi.Decorator`.

[source, java]
----
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()` and `getDelegateQualifiers()` return the delegate type and qualifiers of the decorator.


An instance of `Decorator` exists for every enabled decorator.

[[interceptor]]

==== The `Interceptor` interface

The `Bean` object for an interceptor must implement `jakarta.enterprise.inject.spi.Interceptor`.

[source, java]
----
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()` returns `true` if the interceptor intercepts the specified kind of lifecycle callback or method invocation, and `false` 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.

[source, java]
----
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.

[[observer_method]]

==== The `ObserverMethod` interface

The interface `jakarta.enterprise.inject.spi.ObserverMethod` defines everything the container needs to know about an observer method.

[source, java]
----
public interface ObserverMethod<T> extends Prioritized {
    public Class<?> getBeanClass();
    public Bean<?> getDeclaringBean();
    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.
* `getDeclaringBean()` returns the `Bean` object that declares the observer method. Return value is undefined for synthetic observers.
* `getObservedType()` and `getObservedQualifiers()` return the observed event type and qualifiers.
* `getReception()` returns `IF_EXISTS` for a conditional observer and `ALWAYS` otherwise.
* `getTransactionPhase()` returns the appropriate transaction phase for a transactional observer method or `IN_PROGRESS` otherwise.
* `getPriority()` this method inherited from <<prioritized, `Prioritized` 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 priority `APPLICATION + 500` is assumed.
* `notify()` calls the observer method, as defined in <<observer_notification>>.
* `isAsync()` returns `true` if the method is an asynchronous observer method otherwise returns `false`.


An instance of `ObserverMethod` must exist for every observer method of every enabled bean.


[[prioritized]]

==== The `Prioritized` interface

CDI 2.0 introduced the prioritized interface to add programmatic priority to custom SPI implementation.

[source, java]
----
public interface Prioritized {
    int getPriority();
}
----


[[injectiontarget]]

=== The `Producer` and `InjectionTarget` interfaces

The interface `jakarta.enterprise.inject.spi.Producer` provides a generic operation for producing an instance of a type.

[source, java]
----
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 by `produce()` may be a proxy.
* `dispose()` does nothing.
* `getInjectionPoints()` returns the set of `InjectionPoint` 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 of `InjectionPoint` 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.

[source, java]
----
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()`.

[[beanmanager]]

=== The `BeanManager` object

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:

[source, java]
----
@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.

[[provider_full]]

==== Obtaining a reference to the CDI container in {cdi_full}

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.

[[bm_obtain_injectable_reference_full]]

==== Obtaining an injectable reference in {cdi_full}

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>>.

[[bm_obtain_unmanaged_instance]]

==== Obtaining non-contextual instance

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:

[source,java]
----
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();
----

[[bm_obtain_bean_by_type_full]]

==== Obtaining a `Bean` by type in {cdi_full}

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>>.

[[bm_obtain_bean_by_name_full]]

==== Obtaining a `Bean` by name in {cdi_full}

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>>.

[[bm_obtain_passivation_capable_bean]]

==== Obtaining a passivation capable bean by identifier

The method `BeanManager.getPassivationCapableBean()` returns the `PassivationCapable` bean with the given identifier (see <<passivation_capable>>).

[source, java]
----
public Bean<?> getPassivationCapableBean(String id);
----

[[bm_validate_ip]]

==== Validating an injection point

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.

[source, java]
----
public void validate(InjectionPoint injectionPoint);
----

[[bm_decorator_resolution]]

==== Decorator resolution

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>>.

[source, java]
----
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.

[[bm_interceptor_resolution_full]]

==== Interceptor resolution in {cdi_full}

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>>.

[[bm_determining_annotation_full]]

==== 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.

[source, java]
----
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);
----

[[bm_determining_hash]]

==== Determining the hash code and equivalence of qualifiers and interceptor bindings

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>>.

[source, java]
----
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`.

[source, java]
----
public int getQualifierHashCode(Annotation qualifier);
public int getInterceptorBindingHashCode(Annotation interceptorBinding);
----

[[bm_obtain_elresolver]]

==== Obtaining the `ELResolver`

The method `BeanManager.getELResolver()` returns the `jakarta.el.ELResolver` specified in <<el>>.

[source, java]
----
public ELResolver getELResolver();
----

[[bm_obtain_annotatedtype]]

==== Obtaining an `AnnotatedType` for a class

The method `BeanManager.createAnnotatedType()` returns an `AnnotatedType` that may be used to read the annotations of the given Java class or interface.

[source, java]
----
public <T> AnnotatedType<T> createAnnotatedType(Class<T> type);
----

[[bm_obtain_injectiontarget]]

==== Obtaining an `InjectionTarget` for a class

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.

[source, java]
----
public <T> InjectionTargetFactory<T> getInjectionTargetFactory(AnnotatedType<T> type);
----

[source, java]
----
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 an `AnnotatedTypeConfigurator` as defined in <<annotated_type_configurator>> to configure the `AnnotatedType` used to create the `InjectionTargetFactory`.
Subsequent invocations of the `configure()` method within one `InjectionTargetFactory` instance will always return the same `AnnotatedTypeConfigurator` instance.
Once `createInjectionTarget()` method has been invoked, any invocations of `configure()` throws an `IllegalStateException`.

[[bm_obtain_producer]]

==== Obtaining a `Producer` for a field or method

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.

[source, java]
----
public <X> ProducerFactory<X> getProducerFactory(AnnotatedField<? super X> field, Bean<X> declaringBean);
public <X> ProducerFactory<X> getProducerFactory(AnnotatedMethod<? super X> method, Bean<X> declaringBean);
----

[source, java]
----
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.


[[bm_obtain_injectionpoint]]

==== Obtaining an `InjectionPoint`

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.

[source, java]
----
public InjectionPoint createInjectionPoint(AnnotatedField<?> field);
public InjectionPoint createInjectionPoint(AnnotatedParameter<?> parameter);
----

[[bm_obtain_beanattributes]]

==== Obtaining a `BeanAttributes`

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.

[source, java]
----
public <T> BeanAttributes<T> createBeanAttributes(AnnotatedType<T> type);
public BeanAttributes<?> createBeanAttributes(AnnotatedMember<?> member);
----

[[bm_obtain_bean]]

==== Obtaining a `Bean`

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 returned `Bean`, and the return values of `isAlternative()`, and
* a class, which determines the return value of `Bean.getClass()`.
* an `InjectionTargetFactory`, which is used to obtain an `InjectionTarget`. The `InjectionTarget` is used to create and destroy instances of the bean, to perform dependency injection and lifecycle callbacks, and which determines the return value of `Bean.getInjectionPoints()`.


[source, java]
----
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 returned `Bean`, and the return values of `isAlternative()`, and
* a class, which determines the return value of `Bean.getClass()`.
* a `ProducerFactory`, which is used to obtain a `Producer`. The `Producer` is used to create and destroy instances of the bean, and which determines the return value of `Bean.getInjectionPoints()`.


[source, java]
----
public <T, X> Bean<T> createBean(BeanAttributes<T> attributes, Class<X> beanClass,
                          ProducerFactory<X> producer);
----

[[bm_obtain_extension]]

==== Obtaining the instance of an `Extension`

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.

[source, java]
----
public <T extends Extension> T getExtension(Class<T> extensionClass);
----

[[bm_obtain_interception_factory]]

==== Obtain an `InterceptionFactory`

The method `BeanManager.getInterceptionFactory()` returns an `InterceptionFactory` for the provided type as defined in <<interception_factory>>.

[source, java]
----
<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.

[[bm_obtain_instance_full]]

==== Obtain an `Instance` in {cdi_full}

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>>.

[[alternative_metadata_sources]]

=== Alternative metadata sources

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.

[source, java]
----
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 call `AnnotatedMethod.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 call `AnnotatedField.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.

[source, java]
----
public interface AnnotatedField<X>
        extends AnnotatedMember<X> {
    public Field getJavaMember();
}
----

The interface `jakarta.enterprise.inject.spi.AnnotatedMethod` exposes the `Method` object.

[source, java]
----
public interface AnnotatedMethod<X>
        extends AnnotatedCallable<X> {
    public Method getJavaMember();
}
----

The interface `jakarta.enterprise.inject.spi.AnnotatedConstructor` exposes the `Constructor` object.

[source, java]
----
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.

[source, java]
----
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.

[source, java]
----
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.

[source, java]
----
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.

[source, java]
----
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>)` returns `true` if the program element has an annotation of the given annotation type, or `false` 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()` and `Annotated.getAnnotation()` to read any bean annotations defined by this specification, and
* call `AnnotatedType.getConstructors()`, `AnnotatedType.getMethods()` and `AnnotatedType.getFields()` to determine the members of a bean class.

[[annotated_type_configurator]]

==== `AnnotatedTypeConfigurator` SPI

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 an `AnnotatedType`
* `jakarta.enterprise.inject.spi.configurator.AnnotatedFieldConfigurator` (defined in <<annotated_field_configurator>>) to configure an `AnnotatedField`
* `jakarta.enterprise.inject.spi.configurator.AnnotatedConstructorConfigurator` (defined in <<annotated_constructor_configurator>>) to configure an `AnnotatedConstructor`
* `jakarta.enterprise.inject.spi.configurator.AnnotatedMethodConfigurator` (defined in <<annotated_method_configurator>>) to configure an `AnnotatedMethod`
* `jakarta.enterprise.inject.spi.configurator.AnnotatedParameterConfigurator` (defined in <<annotated_parameter_configurator>>) to configure an `AnnotatedParameter`

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 in <<before_bean_discovery>>
* `ProcessAnnotatedType` as defined in <<process_annotated_type>>
* `AfterTypeDiscovery` as defined in <<after_type_discovery>>


[source, java]
----
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 original `AnnotatedType` 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 of `AnnotatedMethodConfigurator` to configure annotations on methods
* `filterMethods()` returns a `Stream<AnnotatedMethodsConfigurator>` filtered by applying the provided Predicate on `methods()`
* `fields()` returns a set of `AnnotatedFieldConfigurator` to configure annotations on fields
* `filterFields()` returns a `Stream<AnnotatedFieldConfigurator>` filtered by applying the provided Predicate on `fields()`
* `constructors()` returns a set of `AnnotatedConstructorConfigurator` to configure annotations on constructors
* `filterConstructors()` returns a `Stream<AnnotatedConstructorConfigurator>` filtered by applying the provided Predicate on `Constructors()`

[[annotated_method_configurator]]

===== `AnnotatedMethodConfigurator`

`AnnotatedMethodConfigurator` is obtained through `AnnotatedTypeConfigurator` as defined in <<annotated_type_configurator>>

[source, java]
----
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 original `AnnotatedMethod` 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 of `AnnotatedParameterConfigurator` to configure annotations on parameters.
* `filterParams(Predicate<AnnotatedParameter<T>> predicate)` returns a `Stream<AnnotatedParameterConfigurator>` filtered by applying the provided Predicate on `params()`


[[annotated_constructor_configurator]]

===== `AnnotatedConstructorConfigurator`

`AnnotatedConstructorConfigurator` is obtained through `AnnotatedTypeConfigurator` as defined in <<annotated_type_configurator>>

[source, java]
----
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 original `AnnotatedConstructor` 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 of `AnnotatedParameterConfigurator` to configure annotations on parameters.
* `filterParams(Predicate<AnnotatedParameter<T>> predicate)` returns a `Stream<AnnotatedParameterConfigurator>` filtered by applying the provided Predicate on `params()`

[[annotated_parameter_configurator]]

===== `AnnotatedParameterConfigurator`

`AnnotatedParameterConfigurator` is obtained through `AnnotatedMethodConfigurator` (as defined in <<annotated_method_configurator>>) and `AnnotatedConstructorConfigurator` as defined in <<annotated_constructor_configurator>>.

[source, java]
----
public interface AnnotatedParameterConfigurator<T> {
    AnnotatedParameter<T> getAnnotated();
    AnnotatedParameterConfigurator<T> add(Annotation annotation);
    AnnotatedParameterConfigurator<T> remove(Predicate<Annotation> predicate);
    AnnotatedParameterConfigurator<T> removeAll();
}
----

* `getAnnotated()` returns the original `AnnotatedParameter` 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

[[annotated_field_configurator]]

===== `AnnotatedFieldConfigurator`

`AnnotatedFieldConfigurator` is obtained through `AnnotatedTypeConfigurator` as defined in <<annotated_type_configurator>>:

[source, java]
----
public interface AnnotatedFieldConfigurator<T> {

    AnnotatedField<T> getAnnotated();
    AnnotatedFieldConfigurator<T> add(Annotation annotation);
    AnnotatedFieldConfigurator<T> remove(Predicate<Annotation> predicate);
    AnnotatedFieldConfigurator<T> removeAll();
}
----

* `getAnnotated()` returns the original `AnnotatedField` 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


[[init_events]]

=== Container lifecycle events

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_full>>.
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`.

[source, java]
----
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.

[source, java]
----
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_full>>.

As these lifecycle events are fired, the container must also execute <<spi_lite,build compatible extensions>>.
Which phase of build compatible extensions should be executed when is indicated in the description of the corresponding lifecycle events.
Build compatible extensions annotated `@SkipIfPortableExtensionPresent` must be ignored in {cdi_full}, if given portable extension is present.

[[before_bean_discovery]]

==== `BeforeBeanDiscovery` event

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`:

[source, java]
----
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 given `AnnotatedType` 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 in <<annotated_type_configurator>> to easily configure the `AnnotatedType` which will be added at the end of the observer invocation.
The returned `AnnotatedTypeConfigurator` is initialized with type and annotations of the provided class.
* `configureQualifier()` returns a new `AnnotatedTypeConfigurator` as defined in <<annotated_type_configurator>> to configure a new `AnnotatedType` and declares it as a qualifier type.
* `configureInterceptorBinding()` returns a new `AnnotatedTypeConfigurator` as defined in <<annotated_type_configurator>> to configure a new `AnnotatedType` and declares it as an interceptor binding.


[source, java]
----
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 execute the `@Discovery` phase of build compatible extensions at this time.

[[after_type_discovery]]

==== `AfterTypeDiscovery` event

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`.

[source, java]
----
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 given `AnnotatedType` 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 in <<annotated_type_configurator>> to easily configure the `AnnotatedType` which will be added at the end of observer invocation.
The returned `AnnotatedTypeConfigurator` 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.

[source, java]
----
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.


[[after_bean_discovery]]

==== `AfterBeanDiscovery` event

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`:

[source, java]
----
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 type `ProcessSyntheticBean` containing the given `Bean` and then registers the `Bean` with the container, thereby making it available for injection into other beans.
The given `Bean` may implement `Interceptor` or `Decorator`.
+
The second version of the method, returns a new `BeanConfigurator` as defined in <<bean_configurator>> to easily configure the `Bean` 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 type `ProcessSyntheticObserverMethod` containing the given `ObserverMethod` and then registers the `ObserverMethod` with the container, thereby making it available for event notifications.
+
If the given `ObserverMethod` does not override either `ObserverMethod.notify(T)` or `ObserverMethod.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 in <<observer_method_configurator>> to easily configure the `ObserverMethod` 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 custom `Context` object with the container.
* `getAnnotatedType()` and `getAnnotatedTypes()` returns the `AnnotatedType` s discovered or added during container initialization.
The id of an `AnnotatedType` added by the container is not defined.
If the `id` 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.

[source, java]
----
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.

The container must execute the `@Synthesis` phase of build compatible extensions at this time.

[[bean_configurator]]

===== `BeanConfigurator` interface

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 <<bean_attributes_configurator>> plus the following:

* Initialize the bean metadata with one of its `read()` methods.
It can be done from an existing `BeanAttributes`  or by reading metadata on a given `AnnotatedType`, 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 with `id` method.
* Set the priority of the bean, if it is an alternative, with `priority` method.
* Set a callback to create a bean instance with `createWith()` or `produceWith()` method.
* Set a callback to destroy a bean instance with `destroyWith()` or `disposeWith()` method.

If a `BeanConfigurator` has no scope specified, the default scope rules, defined in <<default_scope>>, apply.

[[observer_method_configurator]]

===== `ObserverMethodConfigurator` interface

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 existing `ObserverMethod` with one of its `read()` methods.
* Set the `ObserverMethod` bean class with `beanClass` method.
* Set the type of the observed event with `observedType` method.
* Add a qualifier with `addQualifier` method.
* Set or add multiple qualifiers with `addQualifiers` and `qualifiers` methods.
* Set the `Reception` type with reception method.
* Set the `TransactionPhase` type with `transactionPhase` method.
* Set the priority with `priority` method.
* Define the `EventConsumer` to call on notification with `notifyWith` method.
* Make the observer asynchronous with `async` method.

[[after_deployment_validation]]

==== `AfterDeploymentValidation` event

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`:

[source, java]
----
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.


[source, java]
----
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 execute the `@Validation` phase of build compatible extensions at this time.

[[before_shutdown]]

==== `BeforeShutdown` event

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`:

[source, java]
----
public interface BeforeShutdown {}
----

[source, java]
----
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.

[[process_annotated_type]]

==== `ProcessAnnotatedType` event

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_full>>.

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.

[source, java]
----
public interface ProcessAnnotatedType<X> {
    public AnnotatedType<X> getAnnotatedType();
    public void setAnnotatedType(AnnotatedType<X> type);
    public AnnotatedTypeConfigurator<X> configureAnnotatedType();
    public void veto();
}
----

[source, java]
----
interface ProcessSyntheticAnnotatedType<X> extends ProcessAnnotatedType<X> {
    public Extension getSource();
}
----

* `getAnnotatedType()` returns the `AnnotatedType` object that will be used by the container to read the declared annotations.
* `setAnnotatedType()` replaces the `AnnotatedType`.
* `configureAnnotatedType()` returns an `AnnotatedTypeConfigurator` (as defined in <<annotated_type_configurator>>) initialized with the `AnnotatedType` processed by the event to easily configure the `AnnotatedType` which will be used to replace the original one at the end of observer invocation.
The method always returns the same `AnnotatedTypeConfigurator`
* `veto()` forces the container to ignore the type.
* `getSource()` returns the `Extension` 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.

[source, java]
----
<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 execute the `@Enhancement` phase of build compatible extensions at this time.

[[process_injection_point]]

==== `ProcessInjectionPoint` event

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.

[source, java]
----
public interface ProcessInjectionPoint<T, X> {
    public InjectionPoint getInjectionPoint();
    public void setInjectionPoint(InjectionPoint injectionPoint);
    public InjectionPointConfigurator configureInjectionPoint();
    public void addDefinitionError(Throwable t);
}
----

* `getInjectionPoint()` returns the `InjectionPoint` object that will be used by the container to perform injection.
* `setInjectionPoint()` replaces the `InjectionPoint`.
* `configureInjectionPoint()` returns an `InjectionPointConfigurator` (as defined in <<injection_point_configurator>>) initialized with the `InjectionPoint` processed by the event to easily configure the  `InjectionPoint` which will be used to replace the original one at the end of observer invocation.
The method always returns the same `InjectionPointConfigurator`.
* `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.

[[injection_point_configurator]]

===== `InjectionPointConfigurator` interface

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` with `type` method.
* Add a qualifier with `addQualifier` method.
* Set or add multiple qualifiers with `addQualifiers` and `qualifiers` methods.
* Make the injection point delegate with `delegate` method.
* Make the injection point a transient field with `transientField` method.


[[process_injection_target]]

==== `ProcessInjectionTarget` event

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.

[source, java]
----
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 the `AnnotatedType` representing the bean class.
* `getInjectionTarget()` returns the `InjectionTarget` object that will be used by the container to perform injection.
* `setInjectionTarget()` replaces the `InjectionTarget`.
* `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.

[[process_bean_attributes]]

==== `ProcessBeanAttributes` event

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.

[source, java]
----
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 the `AnnotatedType` representing the bean class, the `AnnotatedMethod` representing the producer field, or the `AnnotatedField` representing the producer field.
* `getBeanAttributes()` returns the `BeanAttributes` object that will be used by the container to manage instances of the bean.
* `setBeanAttributes()` replaces the `BeanAttributes`.
* `configureBeanAttributes()` returns a `BeanAttributesConfigurator` (as defined in <<bean_attributes_configurator>>) initialized with the `BeanAttributes` processed by the event to easily configure the  `BeanAttributes` which will be used to replace the original one at the end of observer invocation.
The method always returns the same `BeanAttributesConfigurator`.
* `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.


[[bean_attributes_configurator]]

===== `BeanAttributesConfigurator` interface

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` or `addTransitiveTypeClosure` 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` and `qualifiers` methods.
* Add a stereotype with `addStereotype` method.
* Set or add multiple stereotypes with `addStereotypes` and `stereotypes` methods.
* Set the bean name `name` method.
* Make the bean an alternative with `alternative` methods.


[[process_bean]]

==== `ProcessBean` event

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 type `ProcessManagedBean<X>`.
* For a producer method with method return type `T` of a bean with bean class `X`, the container must raise an event of type `ProcessProducerMethod<T, X>`.
* For a producer field with field type `T` of a bean with bean class `X`, the container must raise an event of type `ProcessProducerField<T, X>`.
* For a custom implementation of `Bean`, the container must raise an event of type `ProcessSyntheticBean<X>`.

The interface `jakarta.enterprise.inject.spi.ProcessBean` is a supertype of all these event types:

[source, java]
----
public interface ProcessBean<X> {
    public Annotated getAnnotated();
    public Bean<X> getBean();
    public void addDefinitionError(Throwable t);
}
----

* `getAnnotated()` returns the `AnnotatedType` representing the bean class, the `AnnotatedMethod` representing the producer method, or the `AnnotatedField` representing the producer field. If invoked upon a `ProcessSyntheticBean` event, non-portable behavior results and the returned value should be ignored.
* `getBean()` returns the `Bean` object that is about to be registered.
The `Bean` may implement `Interceptor` or `Decorator`.
* `addDefinitionError()` registers a definition error with the container, causing the container to abort deployment after bean discovery is complete.


[source, java]
----
public interface ProcessManagedBean<X>
        extends ProcessBean<X> {
    public AnnotatedType<X> getAnnotatedBeanClass();
}
----

[source, java]
----
public interface ProcessProducerMethod<T, X>
        extends ProcessBean<X> {
    public AnnotatedMethod<T> getAnnotatedProducerMethod();
    public AnnotatedParameter<T> getAnnotatedDisposedParameter();
}
----

[source, java]
----
public interface ProcessProducerField<T, X>
        extends ProcessBean<X> {
    public AnnotatedField<T> getAnnotatedProducerField();
    public AnnotatedParameter<T> getAnnotatedDisposedParameter();
}
----

[source, java]
----
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 execute the bean-related part of `@Registration` phase of build compatible extensions at this time.

[[process_producer]]

==== `ProcessProducer` event

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.

[source, java]
----
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 the `AnnotatedField` representing the producer field or the `AnnotatedMethod` representing the producer method.
* `getProducer()` returns the `Producer` object that will be used by the container to call the producer method or read the producer field.
* `setProducer()` replaces the `Producer`.
* `configureProducer()` returns a `ProducerConfigurator` (as defined in <<producer_configurator>>) initialized with the `Producer` processed by this event to configure the `Producer` 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`.

[source, java]
----
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.

[[producer_configurator]]

===== `ProducerConfigurator` interface

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.

[[process_observer_method]]

==== `ProcessObserverMethod` event

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()`.

[source, java]
----
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();
}
----

[source, java]
----
public interface ProcessSyntheticObserverMethod<T, X> extends ProcessObserverMethod<T, X> {
    public Extension getSource();
}
----

* `getAnnotatedMethod()` returns the `AnnotatedMethod` representing the observer method. If invoked upon a `ProcessSyntheticObserverMethod` event, non-portable behavior results and the returned value should be ignored.
* `getObserverMethod()` returns the `ObserverMethod` 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 the `ObserverMethod`.
* `configureObserverMethod()` returns an `ObserverMethodConfigurator` (as defined in <<observer_method_configurator>>) initialized with the `ObserverMethod` processed by the event to easily configure the  `ObserverMethod` which will be used to replace the original one at the end of observer invocation.
The method always returns the same `ObserverMethodConfigurator`.
* `veto()` forces the container to ignore the `ObserverMethod`.
* `getSource()` returns the `Extension` 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.

The container must execute the observer-related part of `@Registration` phase of build compatible extensions at this time.

[[configurators]]

=== Configurators interfaces

CDI 2.0 introduced the following Configurators interface:

* <<annotated_type_configurator>> for `AnnotatedType` configuration
* <<injection_point_configurator>> for `InjectionPoint` configuration
* <<bean_attributes_configurator>> for `BeanAttributes` configuration
* <<bean_configurator>> for `Bean` configuration
* <<observer_method_configurator>> for `ObserverMethod` configuration
* <<producer_configurator>> for `Producer` configuration

The container must provide implementation for all these configurators and make them available in matching container lifecycle events as defined in <<init_events>>.

[[interception_factory]]

=== The `InterceptionFactory` interface

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.

[source, java]
----
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 of `createInterceptedInstance()` method.
Ignored methods should never be invoked upon the wrapper instance. 
Otherwise, unpredictable behavior results.
* `configure()` returns an `AnnotatedTypeConfigurator` (as defined in <<annotated_type_configurator>>) 
initialized with the `AnnotatedType` created either for the class passed to `BeanManager.createInterceptionFactory(CreationalContext, Class)` or derived from the `InterceptionFactory` parameter injection point.
The method always return the same `AnnotatedTypeConfigurator`
* `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 an `IllegalStateException`.
If the type of the instance is not proxyable as defined in <<unproxyable>> an `UnproxyableResolutionException` exception is thrown.
This rule can be loosen by calling `ignoreFinalMethods()` 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 <<bm_obtain_interception_factory>>.

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`:

[source, java]
----
@Produces
@RequestScoped
public Product createInterceptedProduct(InterceptionFactory<Product> interceptionFactory) {
  interceptionFactory.configure().add(ActionBinding.Literal.INSTANCE);
  return interceptionFactory.createInterceptedInstance(new Product());
}
----
