diff --git a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/BuildCompatibleExtension.java b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/BuildCompatibleExtension.java
index 0cb55a54..d334a7aa 100644
--- a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/BuildCompatibleExtension.java
+++ b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/BuildCompatibleExtension.java
@@ -18,9 +18,10 @@
*
{@link Validation @Validation}
*
*
- * Extension methods may declare arbitrary number of parameters. Which parameters may be declared depends
- * on the particular execution phase and is documented in the corresponding extension annotation.
- * All the parameters will be provided by the container when the extension method is executed.
+ * Extension methods may declare arbitrary number of parameters. In each execution phase, different types
+ * of parameters may be declared, as documented in the corresponding extension annotation. All the parameters
+ * will be provided by the container when the extension method is invoked. If an extension method declares
+ * a parameter of a type unsupported in the execution phase, the container treats it as a deployment problem.
*
* Extension methods may be assigned a priority using {@link jakarta.annotation.Priority @Priority}.
* Extension methods with smaller priority values are invoked first. Extension methods without specified priority
@@ -28,7 +29,8 @@
* If two extension methods have equal priority, the ordering between them is undefined. Note that priority
* only affects order of extension methods in a single phase.
*
- * If the extension declares multiple extension methods, they are all invoked on the same instance of the class.
+ * For each build compatible extension, the container creates a single instance. All extension methods
+ * are invoked on the same instance.
*
* When extension methods are invoked, a CDI container does not have to be running, so calling {@code CDI.current()}
* from an extension method, or attempting to access a running CDI container in any other way, results in
diff --git a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/package-info.java b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/package-info.java
new file mode 100644
index 00000000..30d5c28c
--- /dev/null
+++ b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/package-info.java
@@ -0,0 +1,13 @@
+/**
+ *
The build compatible extension SPI. See:
+ *
+ *
+ * - {@link jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension}
+ * - {@link jakarta.enterprise.inject.build.compatible.spi.Discovery}
+ * - {@link jakarta.enterprise.inject.build.compatible.spi.Enhancement}
+ * - {@link jakarta.enterprise.inject.build.compatible.spi.Registration}
+ * - {@link jakarta.enterprise.inject.build.compatible.spi.Synthesis}
+ * - {@link jakarta.enterprise.inject.build.compatible.spi.Validation}
+ *
+ */
+package jakarta.enterprise.inject.build.compatible.spi;
diff --git a/spec/src/main/asciidoc/core/packagingdeployment.asciidoc b/spec/src/main/asciidoc/core/packagingdeployment.asciidoc
index 7dce658a..b07ef542 100644
--- a/spec/src/main/asciidoc/core/packagingdeployment.asciidoc
+++ b/spec/src/main/asciidoc/core/packagingdeployment.asciidoc
@@ -2,7 +2,8 @@
== Packaging and deployment
-Before an application is started, or during application startup, the container must perform _bean discovery_, execute build compatible extensions, and detect definition errors and deployment problems.
+At deployment time, the container must perform _bean discovery_, execute <>, and detect definition errors and deployment problems.
+The term _deployment time_ in {cdi_lite} means before the application is started, such as during application compilation, or during application startup at latest.
Bean discovery is the process of determining:
@@ -10,7 +11,7 @@ Bean discovery is the process of determining:
* Which alternatives and interceptors are _enabled_
* The _ordering_ of enabled interceptors
-Additional beans may be registered programmatically via <>.
+Additional beans may be registered programmatically using build compatible extensions.
[[bean_archive]]
@@ -34,8 +35,11 @@ An _implicit bean archive_ is:
* an archive which contains a `beans.xml` file that is empty, or,
* an archive which contains a `beans.xml` file that has `bean-discovery-mode` attribute set to `annotated`
-When determining which archives are bean archives, the container must consider all JAR archives available through implementation-specific means.
-Implementations are required to document how the candidate JAR archives are found.
+Any other archive which contains a `beans.xml` file is not portable in {cdi_lite}.
+More kinds of bean archives exist in {cdi_full}.
+
+When determining which archives are bean archives, the container must consider all archives that constitute the application.
+Implementations are encouraged to document how the candidate archives are found in more detail.
The `beans.xml` file must be named:
@@ -50,14 +54,27 @@ Implicit bean archives are likely to contain classes which are not deployed as b
An extension may be deployed in any archive, including those that are not bean archives.
+[[deployment]]
+
+=== Deployment
+
+At deployment time, the container performs the following steps:
+
+* First, the container must perform type discovery, as defined in <>.
+ As part of that, the container must execute the <> and <> phases of build compatible extensions.
+* Next, the container must perform bean discovery, as defined in <>.
+ As part of that, the container must execute the <> and <> phases of build compatible extensions.
+* Finally, the container must detect deployment problems by validating bean dependencies.
+ As part of that, the container must execute the <> phase of build compatible extensions.
+
+At any step, the container must abort deployment if any definition errors or deployment problems exist, as defined in <>.
+
[[initialization]]
=== Application initialization lifecycle
-// TODO related to https://github.com/eclipse-ee4j/cdi/issues/482
-// also related to https://github.com/eclipse-ee4j/cdi/issues/496
-// Capture init process WRT build compatible extensions + type discovery + bean discovery
-// see <> for format that is used for CDI Full
+{cdi_lite} does not require the container to perform any other initialization during application startup.
+With deployment complete, the container begins directing requests to the application.
[[shutdown]]
@@ -78,9 +95,9 @@ The container automatically discovers managed beans (according to the rules of <
First the container must discover types.
The container discovers each Java class with a bean defining annotation in an implicit bean archive.
-// TODO at this point, we should probably mention build compatible extensions and how you can get notified of events and change these types
-// we should mention Enhancement phase here and link to the relevant doc part
-// related to https://github.com/eclipse-ee4j/cdi/issues/483
+The container must also execute the `@Discovery` phase of build compatible extensions and discover all classes added using the `ScannedClasses` API.
+
+When all types are discovered, the container must execute the `@Enhancement` phase of build compatible extensions and alter its metadata representation of discovered types accordingly.
[[bean_discovery_steps]]
@@ -91,24 +108,19 @@ For every type in the set of discovered types (as defined in <>.
-// TODO mention any events we fire for build compatible extensions at this point - Processing
-// e.g. if we have an equivalent of ProcessBeanAttributes and/or ProcessBean
-// related to https://github.com/eclipse-ee4j/cdi/issues/483
-For each enabled bean, the container must search the class for producer methods and fields, as defined in <> and in <>, including resources, and for each producer:
-
-// TODO mention any events we fire for build compatible extensions at this point - Processing
-// e.g. if we have an equivalent of ProcessInjectionPoint and/or ProcessProducer and/or ProcessBeanAttributes and/or ProcessBean
-// related to https://github.com/eclipse-ee4j/cdi/issues/483
-
-For each enabled bean, the container must search the class for observer methods, and for each observer method:
-
-// TODO mention build compatible extension equivalent - Processing
-// e.g. if we have an equivalent of ProcessObserverMethod
-// related to https://github.com/eclipse-ee4j/cdi/issues/483
+For each enabled bean, the container must search the class for producer methods and fields, as defined in <> and in <>, including resources, and for disposer methods as defined in <>, and for observer methods.
Then, the container registers the `Bean` and `ObserverMethod` objects:
* For each enabled bean that is not an interceptor, the container registers an instance of the `Bean` interface defined in <>.
* For each enabled interceptor, the container registers an instance of the `Interceptor` interface defined in <>.
* For each observer method of every enabled bean, the container registers an instance of the `ObserverMethod` interface defined in <>.
+
+The container must execute the `@Registration` phase of build compatible extensions for each registered bean, interceptor, and observer method.
+
+Next, the container must execute the `@Synthesis` phase of build compatible extensions.
+For each registered synthetic bean, the container registers an instance of the `Bean` interface.
+For each registered synthetic observer, the container registers an instance of the `ObserverMethod` interface.
+
+Finally, the container must execute the `@Registration` phase of build compatible extensions for each synthetic bean and synthetic observer method.
diff --git a/spec/src/main/asciidoc/core/packagingdeployment_full.asciidoc b/spec/src/main/asciidoc/core/packagingdeployment_full.asciidoc
index 798e0cf4..2f91a043 100644
--- a/spec/src/main/asciidoc/core/packagingdeployment_full.asciidoc
+++ b/spec/src/main/asciidoc/core/packagingdeployment_full.asciidoc
@@ -3,7 +3,8 @@
== Packaging and deployment in {cdi_full}
This chapter replaces <> for the purpose of {cdi_full}.
-In case of overlap, the <> chapter should be considered merely informative.
+The <> chapter should be considered merely informative.
+In {cdi_full}, the term _deployment time_ always means during application startup.
When an application is started, the container must perform _bean discovery_, detect definition errors and deployment problems and raise events that allow portable extensions to integrate with the deployment lifecycle.
@@ -108,7 +109,7 @@ First the container must discover types.
The container discovers:
* each Java class, interface (excluding the special kind of interface declaration _annotation type_) or enum deployed in an explicit bean archive, and
-* each Java class with a bean defining annotation in an implicit bean archive.
+* each Java class with a bean defining annotation in an implicit bean archive,
that is not excluded from discovery by an _exclude filter_ as defined in <>.
diff --git a/spec/src/main/asciidoc/core/spi_full.asciidoc b/spec/src/main/asciidoc/core/spi_full.asciidoc
index 7457cba5..fccaeab5 100644
--- a/spec/src/main/asciidoc/core/spi_full.asciidoc
+++ b/spec/src/main/asciidoc/core/spi_full.asciidoc
@@ -884,6 +884,10 @@ Lifecycle events described below can be grouped into two categories:
Note that the chronological order of these events is specified in <>.
+As these lifecycle events are fired, the container must also execute <>.
+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
@@ -928,6 +932,7 @@ If any observer method of the `BeforeBeanDiscovery` event throws an exception, t
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]]
@@ -1026,6 +1031,7 @@ If any observer method of the `AfterBeanDiscovery` event throws an exception, th
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]]
@@ -1096,6 +1102,8 @@ If any `AfterDeploymentValidation` method is called outside of the observer meth
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
@@ -1175,6 +1183,8 @@ If any observer method of a `ProcessAnnotatedType` event throws an exception, th
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
@@ -1397,6 +1407,8 @@ If any observer method of a `ProcessBean` event throws an exception, the excepti
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
@@ -1497,6 +1509,8 @@ If any observer method of a `ProcessObserverMethod` event throws an exception, t
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
diff --git a/spec/src/main/asciidoc/core/spi_lite.asciidoc b/spec/src/main/asciidoc/core/spi_lite.asciidoc
index bf1f4421..f5d33204 100644
--- a/spec/src/main/asciidoc/core/spi_lite.asciidoc
+++ b/spec/src/main/asciidoc/core/spi_lite.asciidoc
@@ -2,11 +2,387 @@
== Build compatible extensions
-// TODO
-[NOTE]
-====
-TBD
-====
-
-// Must mention that Build Compatible Extensions do not have access to the CDI container,
-// as there may not be one running! Calling `CDI.current()` inside them results in non-portable behavior.
+A build compatible extension may integrate with the container during deployment time, as defined in <>.
+
+[[bce]]
+
+=== The `BuildCompatibleExtension` interface
+
+A build compatible extension is a service provider of the `jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension` interface, declared in `META-INF/services`.
+
+[source, java]
+----
+public interface BuildCompatibleExtension {}
+----
+
+Build compatible extensions can define arbitrary `public`, non-`static`, `void`-returning methods without type parameters, annotated with one of the extension annotations.
+Such methods are called _extension methods_.
+
+Extension annotations correspond to extension execution phases:
+
+* `@Discovery`
+* `@Enhancement`
+* `@Registration`
+* `@Synthesis`
+* `@Validation`
+
+Extension methods may declare arbitrary number of parameters.
+In each execution phase, different types of parameters may be declared.
+All the parameters will be provided by the container when the extension method is invoked.
+If an extension method declares a parameter of a type unsupported in the execution phase, the container treats it as a deployment problem.
+
+For each build compatible extension, the container creates a single instance.
+All extension methods are invoked on the same instance.
+
+The invocation order for extension methods may be controlled using the `@Priority` annotation.
+If an extension method does not have the `@Priority` annotation, the default priority `jakarta.interceptor.Interceptor.Priority.APPLICATION + 500` is assumed.
+If two extension methods have equal priority, the ordering between them is undefined.
+Note that priority only affects order of extension methods in a single phase.
+
+If an extension method throws an exception, the container treats it as a deployment problem.
+
+At deployment time, CDI container does not have to be running, so calling `CDI.current()` from an extension method, or attempting to access a running CDI container in any other way, results in non-portable behavior.
+
+[[bce_discovery]]
+
+=== The `@Discovery` phase
+
+In this phase, build compatible extensions may register additional classes to be scanned during type discovery, and register custom CDI meta-annotations.
+
+Extension methods annotated `@Discovery` may declare parameters of the following types:
+
+* `ScannedClasses`
+* `MetaAnnotations`
+* `Messages` (see <>)
+
+[source, java]
+----
+public interface ScannedClasses {
+ void add(String className);
+}
+----
+
+[source, java]
+----
+public interface MetaAnnotations {
+ ClassConfig addQualifier(Class extends Annotation> annotation);
+ ClassConfig addInterceptorBinding(Class extends Annotation> annotation);
+ ClassConfig addStereotype(Class extends Annotation> annotation);
+
+ void addContext(Class extends Annotation> scopeAnnotation, Class extends AlterableContext> contextClass);
+ void addContext(Class extends Annotation> scopeAnnotation, boolean isNormal, Class extends AlterableContext> contextClass);
+}
+----
+
+If the `addQualifier`, `addInterceptorBinding` or `addStereotype` method is called, the return value allows configuring meta-annotations on the qualifier, interceptor binding or stereotype annotation and its members.
+
+[[bce_enhancement]]
+
+=== The `@Enhancement` phase
+
+In this phase, build compatible extensions may alter annotations on discovered types.
+
+Extension methods annotated `@Enhancement` must declare exactly one parameter of one of the following types:
+
+* `ClassConfig` or `ClassInfo`
+* `MethodConfig` or `MethodInfo`
+* `FieldConfig` or `FieldInfo`
+
+[source, java]
+----
+public interface ClassConfig extends DeclarationConfig {
+ ClassInfo info();
+
+ ClassConfig addAnnotation(Class extends Annotation> annotationType);
+ ClassConfig addAnnotation(AnnotationInfo annotation);
+ ClassConfig addAnnotation(Annotation annotation);
+ ClassConfig removeAnnotation(Predicate predicate);
+ ClassConfig removeAllAnnotations();
+
+ Collection constructors();
+ Collection methods();
+ Collection fields();
+}
+
+public interface ClassInfo extends DeclarationInfo {
+ String name();
+ String simpleName();
+ PackageInfo packageInfo();
+ List typeParameters();
+
+ Type superClass();
+ ClassInfo superClassDeclaration();
+ List superInterfaces();
+ List superInterfacesDeclarations();
+
+ boolean isPlainClass();
+ boolean isInterface();
+ boolean isEnum();
+ boolean isAnnotation();
+ boolean isRecord();
+ boolean isAbstract();
+ boolean isFinal();
+ int modifiers();
+
+ Collection constructors();
+ Collection methods();
+ Collection fields();
+ Collection recordComponents();
+}
+----
+
+When an extension method declares a parameter of type `ClassConfig` or `ClassInfo`, it will be called for each discovered class matching the criteria defined on the `@Enhancement` annotation.
+It is possible to navigate to constructors, methods and fields from a `ClassConfig` and configure them.
+
+[source, java]
+----
+public interface MethodConfig extends DeclarationConfig {
+ MethodInfo info();
+
+ MethodConfig addAnnotation(Class extends Annotation> annotationType);
+ MethodConfig addAnnotation(AnnotationInfo annotation);
+ MethodConfig addAnnotation(Annotation annotation);
+ MethodConfig removeAnnotation(Predicate predicate);
+ MethodConfig removeAllAnnotations();
+
+ List parameters();
+}
+
+public interface ParameterConfig extends DeclarationConfig {
+ ParameterInfo info();
+
+ ParameterConfig addAnnotation(Class extends Annotation> annotationType);
+ ParameterConfig addAnnotation(AnnotationInfo annotation);
+ ParameterConfig addAnnotation(Annotation annotation);
+ ParameterConfig removeAnnotation(Predicate predicate);
+ ParameterConfig removeAllAnnotations();
+}
+
+public interface MethodInfo extends DeclarationInfo {
+ String name();
+ List parameters();
+ Type returnType();
+ Type receiverType();
+ List throwsTypes();
+ List typeParameters();
+
+ boolean isConstructor();
+ boolean isStatic();
+ boolean isAbstract();
+ boolean isFinal();
+ int modifiers();
+
+ ClassInfo declaringClass();
+}
+
+public interface ParameterInfo extends DeclarationInfo {
+ String name();
+ Type type();
+
+ MethodInfo declaringMethod();
+}
+----
+
+When an extension method declares a parameter of type `MethodConfig` or `MethodInfo`, it will be called for each method and constructor of each discovered class matching the criteria defined on the `@Enhancement` annotation.
+It is possible to navigate to method parameters from a `MethodConfig` and configure them.
+
+[source, java]
+----
+public interface FieldConfig extends DeclarationConfig {
+ FieldInfo info();
+
+ FieldConfig addAnnotation(Class extends Annotation> annotationType);
+ FieldConfig addAnnotation(AnnotationInfo annotation);
+ FieldConfig addAnnotation(Annotation annotation);
+ FieldConfig removeAnnotation(Predicate predicate);
+ FieldConfig removeAllAnnotations();
+}
+
+public interface FieldInfo extends DeclarationInfo {
+ String name();
+ Type type();
+
+ boolean isStatic();
+ boolean isFinal();
+ int modifiers();
+
+ ClassInfo declaringClass();
+}
+----
+
+When an extension method declares a parameter of type `FieldConfig` or `FieldInfo`, it will be called for each field of each discovered class matching the criteria defined on the `@Enhancement` annotation.
+
+Additionally, extension methods annotated `@Enhancement` may declare parameters of the following types:
+
+* `Types`
+* `Messages` (see <>)
+
+[source, java]
+----
+public interface Types {
+ Type of(Class> clazz);
+ VoidType ofVoid();
+ PrimitiveType ofPrimitive(PrimitiveType.PrimitiveKind kind);
+ ClassType ofClass(String name);
+ ClassType ofClass(ClassInfo clazz);
+ ArrayType ofArray(Type elementType, int dimensions);
+ ParameterizedType parameterized(Class> genericType, Class>... typeArguments);
+ ParameterizedType parameterized(Class> genericType, Type... typeArguments);
+ ParameterizedType parameterized(ClassType genericType, Type... typeArguments);
+ WildcardType wildcardWithUpperBound(Type upperBound);
+ WildcardType wildcardWithLowerBound(Type lowerBound);
+ WildcardType wildcardUnbounded();
+}
+----
+
+The `Types` interface allows creating representations of the void pseudo-type, primitive types, class types, array types, parameterized types and wildcard types.
+
+To create instances of `AnnotationInfo`, `AnnotationBuilder` can be used.
+
+[[bce_registration]]
+
+=== The `@Registration` phase
+
+In this phase, build compatible extensions may observe registered beans and observers.
+
+Extension methods annotated `@Registration` must declare exactly one parameter of one of the following types:
+
+* `BeanInfo`
+* `InterceptorInfo`
+* `ObserverInfo`
+
+[source, java]
+----
+public interface BeanInfo {
+ ScopeInfo scope();
+ Collection types();
+ Collection qualifiers();
+ ClassInfo declaringClass();
+ boolean isClassBean();
+ boolean isProducerMethod();
+ boolean isProducerField();
+ boolean isSynthetic();
+ MethodInfo producerMethod();
+ FieldInfo producerField();
+ boolean isAlternative();
+ Integer priority();
+ String getName();
+ DisposerInfo disposer();
+ Collection stereotypes();
+ Collection injectionPoints();
+}
+----
+
+When an extension method declares a parameter of type `BeanInfo`, it will be called for each bean whose set of bean types matches the criteria defined on the `@Registration` annotation.
+
+[source, java]
+----
+public interface InterceptorInfo extends BeanInfo {
+ Collection interceptorBindings();
+ boolean intercepts(InterceptionType interceptionType);
+}
+----
+
+When an extension method declares a parameter of type `InterceptorInfo`, it will be called for each interceptor whose set of bean types matches the criteria defined on the `@Registration` annotation.
+
+[source, java]
+----
+public interface ObserverInfo {
+ Type observedType();
+ Collection qualifiers();
+ ClassInfo declaringClass();
+ MethodInfo observerMethod();
+ ParameterInfo eventParameter();
+ BeanInfo bean();
+ boolean isSynthetic();
+ int priority();
+ boolean isAsync();
+ Reception reception();
+ TransactionPhase transactionPhase();
+}
+----
+
+When an extension method declares a parameter of type `ObserverInfo`, it will be called for each observer whose observed event type matches the criteria defined on the `@Registration` annotation.
+
+Additionally, extension methods annotated `@Registration` may declare parameters of the following types:
+
+* `Types`
+* `Messages` (see <>)
+
+[[bce_synthesis]]
+
+=== The `@Synthesis` phase
+
+In this phase, build compatible extensions may register synthetic beans and observers.
+
+Extension methods annotated `@Synthesis` may declare parameters of the following types:
+
+* `SyntheticComponents`
+* `Types`
+* `Messages` (see <>)
+
+[source, java]
+----
+public interface SyntheticComponents {
+ SyntheticBeanBuilder addBean(Class beanClass);
+ SyntheticObserverBuilder addObserver(Class eventType);
+}
+----
+
+The `SyntheticBeanBuilder` and `SyntheticObserverBuilder` interfaces are used to configure:
+
+* bean or observer attributes, such as scope, bean types, qualifiers, or observed event type;
+* class of a bean creation/destruction function or observer notification function;
+* a string-keyed parameter map.
+
+The container creates an instance of the bean creation/destruction function or observer notification function whenever it needs to create an instance of the bean, destroy the instance of the bean, or notify the observer.
+When invoking the bean creation/destruction function or observer notification function, the container passes the parameter map to it.
+
+The parameter map may contain values of the following types:
+
+* `boolean`
+* `int`
+* `long`
+* `double`
+* `String`
+* `Class`
+* `Enum`
+* any annotation type
+* array of any previously mentioned type
+
+When defining the parameter map on `SyntheticBeanBuilder` or `SyntheticObserverBuilder`, it is possible to use `ClassInfo` or `AnnotationInfo` to define parameter values.
+When such parameter is looked up from the parameter map in the synthetic bean creation/destruction function or the synthetic observer notification function, the value will be of type `Class` or the respective annotation type.
+
+[[bce_validation]]
+
+=== The `@Validation` phase
+
+In this phase, build compatible extensions may perform custom validation.
+
+Extension methods annotated `@Validation` may declare parameters of the following types:
+
+* `Types`
+* `Messages`
+
+[source, java]
+----
+public interface Messages {
+ void info(String message);
+ void info(String message, AnnotationTarget relatedTo);
+ void info(String message, BeanInfo relatedTo);
+ void info(String message, ObserverInfo relatedTo);
+
+ void warn(String message);
+ void warn(String message, AnnotationTarget relatedTo);
+ void warn(String message, BeanInfo relatedTo);
+ void warn(String message, ObserverInfo relatedTo);
+
+ void error(String message);
+ void error(String message, AnnotationTarget relatedTo);
+ void error(String message, BeanInfo relatedTo);
+ void error(String message, ObserverInfo relatedTo);
+ void error(Exception exception);
+}
+----
+
+Calling any of the `Messages.error()` methods registers a deployment problem.