diff --git a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/AppArchive.java b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/AppArchive.java deleted file mode 100644 index 67db8acb..00000000 --- a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/AppArchive.java +++ /dev/null @@ -1,162 +0,0 @@ -package jakarta.enterprise.inject.build.compatible.spi; - -import jakarta.enterprise.lang.model.declarations.ClassInfo; -import jakarta.enterprise.lang.model.declarations.FieldInfo; -import jakarta.enterprise.lang.model.declarations.MethodInfo; -import jakarta.enterprise.lang.model.types.Type; -import java.lang.annotation.Annotation; -import java.util.function.Consumer; - -// TODO remove entirely? -public interface AppArchive { - ClassQuery classes(); - - MethodQuery constructors(); // no static initializers - - MethodQuery methods(); // no constructors nor static initializers - - FieldQuery fields(); - - /** - * The {@code exactly} and {@code subtypeOf} methods are additive. - * When called multiple times, they form a union of requested classes (not an intersection). - * For example, - *
{@code - * appArchive.classes() - * .exactly(Foo.class) - * .subtypeOf(Bar.class) - * .forEach(...) - * }- * runs given code for the {@code Foo} class and all subtypes of the {@code Bar} class. - *
- * The {@code annotatedWith} methods are additive. - * When called multiple times, they form a union of requested annotations (not an intersection). - * For example, - *
{@code - * appArchive.classes() - * .annotatedWith(Foo.class) - * .annotatedWith(Bar.class) - * .forEach(...) - * }- * runs given code for all classes annotated either with {@code @Foo} or with {@code @Bar} (or both). - */ - interface ClassQuery { - ClassQuery exactly(Class> clazz); - - ClassQuery subtypeOf(Class> clazz); - - ClassQuery annotatedWith(Class extends Annotation> annotationType); - - void forEach(Consumer
{@code - * appArchive.methods() - * .declaredOn(appArchive.classes().exactly(Foo.class)) - * .declaredOn(appArchive.classes().subtypeOf(Bar.class)) - * .forEach(...) - * }- * runs given code for all methods declared on the {@code Foo} class and on all subtypes of the {@code Bar} class. - * Note that this example can be rewritten as - *
{@code - * appArchive.methods() - * .declaredOn(appArchive.classes().exactly(Foo.class).subtypeOf(Bar.class)) - * .forEach(...) - * }- * which is probably easier to understand. - *
- * The {@code withReturnType} methods are additive. - * When called multiple times, they form a union of requested return types (not an intersection). - * For example, - *
{@code - * appArchive.methods() - * .withReturnType(Foo.class) - * .withReturnType(Bar.class) - * .forEach(...) - * }- * runs given code for all methods that return either {@code Foo} or {@code Bar}. - *
- * The {@code annotatedWith} methods are additive. - * When called multiple times, they form a union of requested annotations (not an intersection). - * For example, - *
{@code - * appArchive.methods() - * .annotatedWith(Foo.class) - * .annotatedWith(Bar.class) - * .forEach(...) - * }- * runs given code for all methods annotated either with {@code @Foo} or with {@code @Bar} (or both). - */ - interface MethodQuery { - MethodQuery declaredOn(ClassQuery classes); - - // equivalent to `withReturnType(Types.of(type))` - MethodQuery withReturnType(Class> type); - - MethodQuery withReturnType(Type type); - - // TODO parameters? - - MethodQuery annotatedWith(Class extends Annotation> annotationType); - - void forEach(Consumer
{@code - * appArchive.fields() - * .declaredOn(appArchive.classes().exactly(Foo.class)) - * .declaredOn(appArchive.classes().subtypeOf(Bar.class)) - * .forEach(...) - * }- * runs given code for all fields declared on the {@code Foo} class and on all subtypes of the {@code Bar} class. - * Note that this example can be rewritten as - *
{@code - * appArchive.fields() - * .declaredOn(appArchive.classes().exactly(Foo.class).subtypeOf(Bar.class)) - * .forEach() - * }- * which is probably easier to understand. - *
- * The {@code ofType} methods are additive. - * When called multiple times, they form a union of requested field types (not an intersection). - * For example, - *
{@code - * appArchive.fields() - * .ofType(Foo.class) - * .ofType(Bar.class) - * .forEach() - * }- * runs given code for all fields that are of type either {@code Foo} or {@code Bar}. - *
- * The {@code annotatedWith} methods are additive. - * When called multiple times, they form a union of requested annotations (not an intersection). - * For example, - *
{@code - * appArchive.fields() - * .annotatedWith(Foo.class) - * .annotatedWith(Bar.class) - * .forEach(...) - * }- * runs given code for all fields annotated either with {@code @Foo} or with {@code @Bar} (or both). - */ - interface FieldQuery { - FieldQuery declaredOn(ClassQuery classes); - - // equivalent to `withReturnType(Types.of(type))` - FieldQuery ofType(Class> type); - - FieldQuery ofType(Type type); - - FieldQuery annotatedWith(Class extends Annotation> annotationType); - - void forEach(Consumer
{@code - * appDeployment.beans() - * .scope(Foo.class) - * .scope(Bar.class) - * .forEach(...) - * }- * runs given code for all beans with the {@code @Foo} scope or the {@code @Bar} scope. - *
- * The {@code type} methods are additive. - * When called multiple times, they form a union of requested bean types (not an intersection). - * For example, - *
{@code - * appDeployment.beans() - * .type(Foo.class) - * .type(Bar.class) - * .forEach(...) - * }- * runs given code for all beans with the {@code Foo} type or the {@code Bar} type (or both). - * Note that bean type is not just the class which declares the bean (or return type of a producer method, - * or type of producer field). All superclasses and superinterfaces are also included in the set of bean types. - *
- * The {@code qualifier} methods are additive. - * When called multiple times, they form a union of requested qualifiers (not an intersection). - * For example, - *
{@code - * appDeployment.beans() - * .qualifier(Foo.class) - * .qualifier(Bar.class) - * .forEach(...) - * }- * runs given code for all beans with the {@code @Foo} qualifier or the {@code @Bar} qualifier (or both). - *
- * The {@code declaringClass} methods are additive. - * When called multiple times, they form a union of requested declaration classes (not an intersection). - * For example, - *
{@code - * appDeployment.beans() - * .declaringClass(Foo.class) - * .declaringClass(Bar.class) - * .forEach(...) - * }- * runs given code for all beans declared on the {@code Foo} class or the {@code Bar} class. - */ - interface BeanQuery { - BeanQuery scope(Class extends Annotation> scopeAnnotation); - - BeanQuery scope(ClassInfo> scopeAnnotation); - - BeanQuery type(Class> beanType); - - BeanQuery type(ClassInfo> beanType); - - BeanQuery type(Type beanType); - - BeanQuery qualifier(Class extends Annotation> qualifierAnnotation); - - BeanQuery qualifier(ClassInfo> qualifierAnnotation); - - BeanQuery declaringClass(Class> declaringClass); - - BeanQuery declaringClass(ClassInfo> declaringClass); - - void forEach(Consumer
{@code - * appDeployment.observers() - * .observedType(Foo.class) - * .observedType(Bar.class) - * .forEach(...) - * }- * runs given code for all observers that observe the {@code Foo} event type or the {@code Bar} event type. - *
- * The {@code qualifier} methods are additive. - * When called multiple times, they form a union of requested qualifiers (not an intersection). - * For example, - *
{@code - * appDeployment.observers() - * .qualifier(Foo.class) - * .qualifier(Bar.class) - * .forEach(...) - * }- * runs given code for all observers with the {@code @Foo} qualifier or the {@code @Bar} qualifier (or both). - *
- * The {@code declaringClass} methods are additive. - * When called multiple times, they form a union of requested declaration classes (not an intersection). - * For example, - *
{@code - * appDeployment.observers() - * .declaringClass(Foo.class) - * .declaringClass(Bar.class) - * .forEach(...) - * }- * runs given code for all observers declared on the {@code Foo} class or the {@code Bar} class. - */ - interface ObserverQuery { - ObserverQuery observedType(Class> observedType); - - ObserverQuery observedType(ClassInfo> observedType); - - ObserverQuery observedType(Type observedType); - - ObserverQuery qualifier(Class extends Annotation> qualifierAnnotation); - - ObserverQuery qualifier(ClassInfo> qualifierAnnotation); - - ObserverQuery declaringClass(Class> declaringClass); - - ObserverQuery declaringClass(ClassInfo> declaringClass); - - void forEach(Consumer
- * Extension processing occurs in 4 phases, corresponding to 4 extension annotations: + * Extension processing occurs in 5 phases, corresponding to 5 extension annotations: *
- * Extension methods can be assigned a priority using {@link jakarta.enterprise.inject.build.compatible.spi.ExtensionPriority @ExtensionPriority}. + * Extension methods can be assigned a priority using {@link ExtensionPriority @ExtensionPriority}. * Note that priority only affects order of extensions in a single phase. *
* If the extension declares multiple methods, they are all invoked on the same instance of the class. diff --git a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/ContextBuilder.java b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/ContextConfig.java similarity index 63% rename from api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/ContextBuilder.java rename to api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/ContextConfig.java index dcaba9b1..de293636 100644 --- a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/ContextBuilder.java +++ b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/ContextConfig.java @@ -3,7 +3,12 @@ import java.lang.annotation.Annotation; import jakarta.enterprise.context.spi.AlterableContext; -public interface ContextBuilder { +/** + * Allows configuring custom scope and context. The only mandatory method is + * {@link ContextConfig#implementation(Class)}, other methods are optional. + * If they aren't called, correct value is deduced from the context implementation class. + */ +public interface ContextConfig { /** * If implementation class is defined using {@link #implementation(Class)}, * this method doesn't have to be called. If it is, it overrides the scope annotation @@ -12,8 +17,8 @@ public interface ContextBuilder { * @param scopeAnnotation scope annotation of the context * @return this {@code ContextBuilder} */ - // if called multiple times, last call wins - ContextBuilder scope(Class extends Annotation> scopeAnnotation); + // TODO if called multiple times, last call wins? or only allow calling once? + ContextConfig scope(Class extends Annotation> scopeAnnotation); /** * If scope annotation is defined using {@link #scope(Class)}, @@ -23,21 +28,18 @@ public interface ContextBuilder { * @param isNormal whether the scope is normal * @return this {@code ContextBuilder} */ - // if called multiple times, last call wins - ContextBuilder normal(boolean isNormal); + // TODO if called multiple times, last call wins? or only allow calling once? + ContextConfig normal(boolean isNormal); /** * Defines the context implementation class. * The implementation class typically provides the scope annotations, and therefore * also whether the scope is a normal scope or pseudoscope, but this can be overridden * using {@link #scope(Class)} and {@link #normal(boolean)}. - *
- * Implementations can impose additional restrictions on what valid parameters are; - * they don't have to accept all implementations of {@link AlterableContext}. * * @param implementationClass context object implementation class * @return this {@code ContextBuilder} */ - // if called multiple times, last call wins - ContextBuilder implementation(Class extends AlterableContext> implementationClass); + // TODO if called multiple times, last call wins? or only allow calling once? + ContextConfig implementation(Class extends AlterableContext> implementationClass); } diff --git a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/Discovery.java b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/Discovery.java index cbfad85e..2fa8b6e8 100644 --- a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/Discovery.java +++ b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/Discovery.java @@ -7,12 +7,12 @@ /** * 1st phase of CDI Lite extension processing. - * Allow registering additional classes to become part of the application. + * Allow registering additional classes to be scanned during bean discovery. * Also allows registering custom CDI meta-annotations. *
* Methods annotated {@code @Discovery} can define parameters of these types: *
* You can also declare a parameter of type {@link Messages Messages} to produce log messages and validation errors. *
diff --git a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/ExactType.java b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/ExactType.java index 141ccb4f..a15e247b 100644 --- a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/ExactType.java +++ b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/ExactType.java @@ -10,7 +10,7 @@ /** * Constraints the {@link Enhancement @Enhancement} or {@link Processing @Processing} method to given types. *
- * If the {@code Enhancement} method has a parameter of type {@code ClassConfig},
+ * If the {@code @Enhancement} method has a parameter of type {@code ClassConfig},
* the method is called once for each given type.
* If the {@code @Enhancement} method has a parameter of type {@code MethodConfig} or {@code FieldConfig},
* the method is called once for each method or field of each given type.
diff --git a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/ExtensionPriority.java b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/ExtensionPriority.java
index 6ec2ca72..93bf41a5 100644
--- a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/ExtensionPriority.java
+++ b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/ExtensionPriority.java
@@ -14,11 +14,11 @@
*
* @see BuildCompatibleExtension
*/
+// TODO this should be removed and @Priority should be used instead;
+// see https://github.com/eclipse-ee4j/common-annotations-api/pull/87
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExtensionPriority {
- // TODO propose allowing @Priority to be present on methods
-
/**
* @return the priority value
*/
diff --git a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/Messages.java b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/Messages.java
index 86bb9767..b2695f67 100644
--- a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/Messages.java
+++ b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/Messages.java
@@ -2,6 +2,10 @@
import jakarta.enterprise.lang.model.AnnotationTarget;
+/**
+ * Allows logging and producing errors during {@link BuildCompatibleExtension} execution.
+ * If an error is produced, application deployment will fail.
+ */
public interface Messages {
/**
* Add a generic information message that is not related to any particular element, or that information is not known.
@@ -85,6 +89,7 @@ public interface Messages {
/**
* Add an error which is related to given {@link BeanInfo}.
+ *
* @param message error message
* @param relatedTo bean to which the message is related
*/
@@ -92,6 +97,7 @@ public interface Messages {
/**
* Add an error which is related to given {@link ObserverInfo}.
+ *
* @param message error message
* @param relatedTo observer to which the message is related
*/
diff --git a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/MetaAnnotations.java b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/MetaAnnotations.java
index b3ee5c33..10fed9fc 100644
--- a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/MetaAnnotations.java
+++ b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/MetaAnnotations.java
@@ -3,16 +3,48 @@
import java.lang.annotation.Annotation;
import java.util.function.Consumer;
+/**
+ * Allows registering custom CDI meta-annotations: qualifiers, interceptor bindings,
+ * stereotypes, and custom scopes.
+ *
+ * @see #addQualifier(Class, Consumer)
+ * @see #addInterceptorBinding(Class, Consumer)
+ * @see #addStereotype(Class, Consumer)
+ * @see #addContext()
+ */
public interface MetaAnnotations {
// TODO this API style is not very common, and makes addContext too different
// I only added it to make Quarkus implementation easier, but should definitely be reconsidered
+ /**
+ * Registers {@code annotation} as a qualifier annotation. Only makes sense if the annotation
+ * isn't meta-annotated {@code @Qualifier}.
+ *
+ * @param annotation annotation type
+ * @param config allows transforming annotations on the {@code annotation}
+ */
void addQualifier(Class extends Annotation> annotation, Consumer
* Methods annotated {@code @Synthesis} can define parameters of these types:
*
* Methods annotated {@code @Validation} can define parameters of these types:
*
- *
diff --git a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/Validation.java b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/Validation.java
index 8361f28d..19db3e0d 100644
--- a/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/Validation.java
+++ b/api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/Validation.java
@@ -11,8 +11,6 @@
*
- *
* If you need to create instances of {@link jakarta.enterprise.lang.model.types.Type Type}, you can also declare