This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 70ee6b5792 org.apache.juneau.common.reflect API improvements
70ee6b5792 is described below

commit 70ee6b5792df4c59e3398f8d597918251cc427cd
Author: James Bognar <[email protected]>
AuthorDate: Mon Nov 24 12:57:13 2025 -0500

    org.apache.juneau.common.reflect API improvements
---
 .../juneau/common/annotation/AnnotationObject.java |  21 +-
 .../common/annotation/AppliedAnnotationObject.java |   2 +-
 .../juneau/jena/annotation/RdfAnnotation.java      |   1 -
 .../apache/juneau/annotation/BeanAnnotation.java   |   1 -
 .../juneau/annotation/BeanIgnoreAnnotation.java    |   1 -
 .../apache/juneau/annotation/BeancAnnotation.java  |   1 -
 .../apache/juneau/annotation/BeanpAnnotation.java  |   1 -
 .../juneau/annotation/ExampleAnnotation.java       |   1 -
 .../juneau/annotation/ExternalDocsAnnotation.java  |   1 -
 .../apache/juneau/annotation/ItemsAnnotation.java  |   1 -
 .../juneau/annotation/MarshalledAnnotation.java    |   1 -
 .../juneau/annotation/NamePropertyAnnotation.java  |   1 -
 .../annotation/ParentPropertyAnnotation.java       |   1 -
 .../apache/juneau/annotation/SchemaAnnotation.java |   1 -
 .../juneau/annotation/SubItemsAnnotation.java      |   1 -
 .../apache/juneau/annotation/SwapAnnotation.java   |   1 -
 .../apache/juneau/annotation/UriAnnotation.java    |   1 -
 .../juneau/csv/annotation/CsvAnnotation.java       |   1 -
 .../juneau/html/annotation/HtmlAnnotation.java     |   1 -
 .../juneau/html/annotation/HtmlLinkAnnotation.java |   1 -
 .../juneau/http/annotation/ContactAnnotation.java  |   1 -
 .../juneau/http/annotation/ContentAnnotation.java  |   1 -
 .../juneau/http/annotation/FormDataAnnotation.java |   1 -
 .../http/annotation/HasFormDataAnnotation.java     |   1 -
 .../juneau/http/annotation/HasQueryAnnotation.java |   1 -
 .../juneau/http/annotation/HeaderAnnotation.java   |   1 -
 .../juneau/http/annotation/LicenseAnnotation.java  |   1 -
 .../juneau/http/annotation/PathAnnotation.java     |   1 -
 .../http/annotation/PathRemainderAnnotation.java   |   1 -
 .../juneau/http/annotation/QueryAnnotation.java    |   1 -
 .../juneau/http/annotation/RequestAnnotation.java  |   1 -
 .../juneau/http/annotation/ResponseAnnotation.java |   1 -
 .../http/annotation/StatusCodeAnnotation.java      |   1 -
 .../juneau/http/annotation/TagAnnotation.java      |   1 -
 .../juneau/json/annotation/JsonAnnotation.java     |   1 -
 .../msgpack/annotation/MsgPackAnnotation.java      |   1 -
 .../juneau/oapi/annotation/OpenApiAnnotation.java  |   1 -
 .../plaintext/annotation/PlainTextAnnotation.java  |   1 -
 .../juneau/soap/annotation/SoapXmlAnnotation.java  |   1 -
 .../juneau/uon/annotation/UonAnnotation.java       |   1 -
 .../annotation/UrlEncodingAnnotation.java          |   1 -
 .../juneau/xml/annotation/XmlAnnotation.java       |   1 -
 .../rest/annotation/OpSwaggerAnnotation.java       |   1 -
 .../juneau/rest/annotation/RestAnnotation.java     |   1 -
 .../rest/annotation/RestDeleteAnnotation.java      |   1 -
 .../rest/annotation/RestDestroyAnnotation.java     |   1 -
 .../rest/annotation/RestEndCallAnnotation.java     |   1 -
 .../juneau/rest/annotation/RestGetAnnotation.java  |   1 -
 .../juneau/rest/annotation/RestInitAnnotation.java |   1 -
 .../rest/annotation/RestInjectAnnotation.java      |   1 -
 .../juneau/rest/annotation/RestOpAnnotation.java   |   1 -
 .../rest/annotation/RestOptionsAnnotation.java     |   1 -
 .../rest/annotation/RestPatchAnnotation.java       |   1 -
 .../juneau/rest/annotation/RestPostAnnotation.java |   1 -
 .../rest/annotation/RestPostCallAnnotation.java    |   1 -
 .../rest/annotation/RestPostInitAnnotation.java    |   1 -
 .../rest/annotation/RestPreCallAnnotation.java     |   1 -
 .../juneau/rest/annotation/RestPutAnnotation.java  |   1 -
 .../rest/annotation/RestStartCallAnnotation.java   |   1 -
 .../juneau/rest/annotation/SwaggerAnnotation.java  |   1 -
 .../common/annotation/AnnotationObject_Test.java   |  24 +-
 .../annotation/AppliedAnnotationObject_Test.java   | 694 +++++++++++++++++++++
 62 files changed, 706 insertions(+), 93 deletions(-)

diff --git 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/annotation/AnnotationObject.java
 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/annotation/AnnotationObject.java
index 738232a7b6..ef9301a34e 100644
--- 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/annotation/AnnotationObject.java
+++ 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/annotation/AnnotationObject.java
@@ -17,7 +17,7 @@
 package org.apache.juneau.common.annotation;
 
 import static java.util.Arrays.*;
-import static org.apache.juneau.common.utils.ThrowableUtils.*;
+import static org.apache.juneau.common.utils.AssertionUtils.*;
 import static org.apache.juneau.common.utils.Utils.*;
 
 import java.lang.annotation.*;
@@ -71,15 +71,13 @@ import org.apache.juneau.common.utils.*;
  *
  * <h5 class='section'>Hashcode Caching:</h5>
  * <p>
- * For performance reasons, the hashcode is calculated once and cached at the 
end of object construction.
- * Subclass constructors <b>must</b> call {@link #postConstruct()} after all 
fields have been set to trigger
- * this calculation.
+ * For performance reasons, the hashcode is calculated once and cached on 
first access.
+ * The hash is computed lazily when {@link #hashCode()} is first called and 
then stored for subsequent calls.
  *
  * <p class='bjava'>
  *     <jk>public</jk> MyAnnotation(Builder <jv>builder</jv>) {
  *             <jk>super</jk>(<jv>builder</jv>);
  *             <jk>this</jk>.<jf>myField</jf> = 
<jv>builder</jv>.<jf>myField</jf>;
- *             postConstruct();  <jc>// Must be called!</jc>
  *     }
  * </p>
  *
@@ -119,7 +117,6 @@ import org.apache.juneau.common.utils.*;
  *             <jk>public</jk> MyAnnotationObject(Builder <jv>builder</jv>) {
  *                     <jk>super</jk>(<jv>builder</jv>);
  *                     <jk>this</jk>.<jf>value</jf> = 
<jv>builder</jv>.<jf>value</jf>;
- *                     postConstruct();
  *             }
  *
  *             <ja>@Override</ja>
@@ -153,6 +150,7 @@ public class AnnotationObject implements Annotation {
                 * @param annotationType The annotation type of the annotation 
implementation class.
                 */
                public Builder(Class<? extends Annotation> annotationType) {
+                       assertArgNotNull("annotationType", annotationType);
                        this.annotationType = annotationType;
                }
 
@@ -200,7 +198,7 @@ public class AnnotationObject implements Annotation {
        @Override /* Overridden from Object */
        public int hashCode() {
                if (hashCode == -1)
-                       throw illegalArg("Programming error. postConstruct() 
was never called on annotation.");
+                       hashCode = AnnotationUtils.hash(this);
                return hashCode;
        }
 
@@ -216,6 +214,8 @@ public class AnnotationObject implements Annotation {
                var m = new LinkedHashMap<String,Object>();
                // @formatter:off
                stream(annotationType().getDeclaredMethods())
+                       // Note: isAnnotation() check is defensive code. For 
properly-formed AnnotationObject instances,
+                       // annotationType() always returns an annotation 
interface, so this condition is always true.
                        .filter(x->x.getParameterCount() == 0 && 
x.getDeclaringClass().isAnnotation())
                        .sorted(Comparator.comparing(Method::getName))
                        .forEach(x -> m.put(x.getName(), 
safeSupplier(()->x.invoke(this))));
@@ -227,11 +227,4 @@ public class AnnotationObject implements Annotation {
        public String toString() {
                return toMap().toString();
        }
-
-       /**
-        * This method must be called at the end of initialization to calculate 
the hashCode one time.
-        */
-       protected void postConstruct() {
-               hashCode = AnnotationUtils.hash(this);
-       }
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/annotation/AppliedAnnotationObject.java
 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/annotation/AppliedAnnotationObject.java
index 5505e3d84c..18ea0dbe6c 100644
--- 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/annotation/AppliedAnnotationObject.java
+++ 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/annotation/AppliedAnnotationObject.java
@@ -110,7 +110,7 @@ import org.apache.juneau.common.reflect.*;
  *     <li>The {@link #on()} method returns the string-based targets
  *     <li>Subclasses may provide additional {@code onClass()}, {@code 
onMethod()}, etc. methods for type-safe access
  *     <li>All builder methods return the builder for method chaining
- *     <li>Use {@link #postConstruct()} after setting all properties to 
finalize hashcode calculation
+ *     <li>Hashcode is calculated lazily on first access and then cached for 
performance
  * </ul>
  *
  * <h5 class='section'>See Also:</h5><ul>
diff --git 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/annotation/RdfAnnotation.java
 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/annotation/RdfAnnotation.java
index 9783f8bf22..ef84d77d5b 100644
--- 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/annotation/RdfAnnotation.java
+++ 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/annotation/RdfAnnotation.java
@@ -241,7 +241,6 @@ public class RdfAnnotation {
                        this.collectionFormat = b.collectionFormat;
                        this.namespace = b.namespace;
                        this.prefix = b.prefix;
-                       postConstruct();
                }
 
                @Override /* Overridden from Rdf */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanAnnotation.java
index 0b0168866a..59201fb15d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanAnnotation.java
@@ -393,7 +393,6 @@ public class BeanAnnotation {
                        this.wo = b.wo;
                        this.writeOnlyProperties = b.writeOnlyProperties;
                        this.xp = b.xp;
-                       postConstruct();
                }
 
                @Override /* Overridden from Bean */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanIgnoreAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanIgnoreAnnotation.java
index 116dd55276..595332eb0a 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanIgnoreAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanIgnoreAnnotation.java
@@ -186,7 +186,6 @@ public class BeanIgnoreAnnotation {
                Object(BeanIgnoreAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from BeanIgnore */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeancAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeancAnnotation.java
index 2ecfca1796..475290b681 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeancAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeancAnnotation.java
@@ -152,7 +152,6 @@ public class BeancAnnotation {
                        super(b);
                        this.description = copyOf(b.description);
                        this.properties = b.properties;
-                       postConstruct();
                }
 
                @Override /* Overridden from Beanc */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanpAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanpAnnotation.java
index e329a7944b..4a0dfb310d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanpAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanpAnnotation.java
@@ -264,7 +264,6 @@ public class BeanpAnnotation {
                        this.type = b.type;
                        this.value = b.value;
                        this.wo = b.wo;
-                       postConstruct();
                }
 
                @Override /* Overridden from Beanp */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ExampleAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ExampleAnnotation.java
index 5cd92dc507..461f501ca8 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ExampleAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ExampleAnnotation.java
@@ -188,7 +188,6 @@ public class ExampleAnnotation {
                        super(b);
                        this.description = copyOf(b.description);
                        this.value = b.value;
-                       postConstruct();
                }
 
                @Override /* Overridden from Example */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ExternalDocsAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ExternalDocsAnnotation.java
index 41eb7165b1..1b68545ee6 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ExternalDocsAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ExternalDocsAnnotation.java
@@ -94,7 +94,6 @@ public class ExternalDocsAnnotation {
                        super(b);
                        this.description = copyOf(b.description);
                        this.url = b.url;
-                       postConstruct();
                }
 
                @Override
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ItemsAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ItemsAnnotation.java
index 76078ff21f..5da32f33d7 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ItemsAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ItemsAnnotation.java
@@ -493,7 +493,6 @@ public class ItemsAnnotation {
                        this.type = b.type;
                        this.ui = b.ui;
                        this.uniqueItems = b.uniqueItems;
-                       postConstruct();
                }
 
                @Override /* Overridden from Items */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledAnnotation.java
index 6c4a077529..95df39796f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledAnnotation.java
@@ -177,7 +177,6 @@ public class MarshalledAnnotation {
                        this.description = copyOf(b.description);
                        this.example = b.example;
                        this.implClass = b.implClass;
-                       postConstruct();
                }
 
                @Override /* Overridden from Marshalled */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/NamePropertyAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/NamePropertyAnnotation.java
index e579a94f2f..2465bc95c6 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/NamePropertyAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/NamePropertyAnnotation.java
@@ -150,7 +150,6 @@ public class NamePropertyAnnotation {
                Object(NamePropertyAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from NameProperty */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ParentPropertyAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ParentPropertyAnnotation.java
index 23190724e9..4f2a6921fb 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ParentPropertyAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/ParentPropertyAnnotation.java
@@ -150,7 +150,6 @@ public class ParentPropertyAnnotation {
                Object(ParentPropertyAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from annotation */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/SchemaAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/SchemaAnnotation.java
index 79f639a5d8..42439482cc 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/SchemaAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/SchemaAnnotation.java
@@ -1081,7 +1081,6 @@ public class SchemaAnnotation {
                        this._then = copyOf(b._then);
                        this._else = copyOf(b._else);
                        this.$defs = copyOf(b.$defs);
-                       postConstruct();
                }
 
                @Override /* Overridden from Schema */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/SubItemsAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/SubItemsAnnotation.java
index 076d30aefe..bbf65cb50c 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/SubItemsAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/SubItemsAnnotation.java
@@ -497,7 +497,6 @@ public class SubItemsAnnotation {
                        this.type = b.type;
                        this.ui = b.ui;
                        this.uniqueItems = b.uniqueItems;
-                       postConstruct();
                }
 
                @Override /* Overridden from SubItems */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/SwapAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/SwapAnnotation.java
index bb33136f73..8f87115392 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/SwapAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/SwapAnnotation.java
@@ -229,7 +229,6 @@ public class SwapAnnotation {
                        this.mediaTypes = copyOf(b.mediaTypes);
                        this.template = b.template;
                        this.value = b.value;
-                       postConstruct();
                }
 
                @Override /* Overridden from Swap */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/UriAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/UriAnnotation.java
index 64da6dc626..1053b4f3cf 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/UriAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/UriAnnotation.java
@@ -174,7 +174,6 @@ public class UriAnnotation {
                Object(UriAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from annotation */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/annotation/CsvAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/annotation/CsvAnnotation.java
index 21aaf19e77..a340be193b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/annotation/CsvAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/annotation/CsvAnnotation.java
@@ -174,7 +174,6 @@ public class CsvAnnotation {
                Object(CsvAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from annotation */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlAnnotation.java
index 6735c34aca..0d0c50c5f9 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlAnnotation.java
@@ -271,7 +271,6 @@ public class HtmlAnnotation {
                        this.noTables = b.noTables;
                        this.render = b.render;
                        this.style = b.style;
-                       postConstruct();
                }
 
                @Override /* Overridden from Html */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlLinkAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlLinkAnnotation.java
index 1fdcac3e98..730d9ae0fa 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlLinkAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlLinkAnnotation.java
@@ -178,7 +178,6 @@ public class HtmlLinkAnnotation {
                        this.description = copyOf(b.description);
                        this.nameProperty = b.nameProperty;
                        this.uriProperty = b.uriProperty;
-                       postConstruct();
                }
 
                @Override /* Overridden from HtmlLink */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ContactAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ContactAnnotation.java
index 4e0fc4ff85..24265a257b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ContactAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ContactAnnotation.java
@@ -112,7 +112,6 @@ public class ContactAnnotation {
                        this.email = b.email;
                        this.name = b.name;
                        this.url = b.url;
-                       postConstruct();
                }
 
                @Override /* Overridden from Contact */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ContentAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ContentAnnotation.java
index 38d81f19da..e5f15f46fc 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ContentAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ContentAnnotation.java
@@ -191,7 +191,6 @@ public class ContentAnnotation {
                        this.description = copyOf(b.description);
                        this.def = b.def;
                        this.schema = b.schema;
-                       postConstruct();
                }
 
                @Override /* Overridden from Content */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormDataAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormDataAnnotation.java
index e88d6495da..3c57bd10b5 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormDataAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/FormDataAnnotation.java
@@ -262,7 +262,6 @@ public class FormDataAnnotation {
                        this.schema = b.schema;
                        this.serializer = b.serializer;
                        this.value = b.value;
-                       postConstruct();
                }
 
                @Override /* Overridden from FormData */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HasFormDataAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HasFormDataAnnotation.java
index 0ee01b137e..24667864f6 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HasFormDataAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HasFormDataAnnotation.java
@@ -100,7 +100,6 @@ public class HasFormDataAnnotation {
                        this.description = copyOf(b.description);
                        this.name = b.name;
                        this.value = b.value;
-                       postConstruct();
                }
 
                @Override
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HasQueryAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HasQueryAnnotation.java
index 1e64b64cfa..dc07ad0d84 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HasQueryAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HasQueryAnnotation.java
@@ -100,7 +100,6 @@ public class HasQueryAnnotation {
                        this.description = copyOf(b.description);
                        this.name = b.name;
                        this.value = b.value;
-                       postConstruct();
                }
 
                @Override
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HeaderAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HeaderAnnotation.java
index fdbaa5e15c..83469886f0 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HeaderAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/HeaderAnnotation.java
@@ -262,7 +262,6 @@ public class HeaderAnnotation {
                        this.schema = b.schema;
                        this.serializer = b.serializer;
                        this.value = b.value;
-                       postConstruct();
                }
 
                @Override /* Overridden from Header */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/LicenseAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/LicenseAnnotation.java
index e03f6f76fe..03fa0df9df 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/LicenseAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/LicenseAnnotation.java
@@ -100,7 +100,6 @@ public class LicenseAnnotation {
                        this.description = copyOf(b.description);
                        this.name = b.name;
                        this.url = b.url;
-                       postConstruct();
                }
 
                @Override /* Overridden from License */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/PathAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/PathAnnotation.java
index 29a34f1207..93e3f88754 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/PathAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/PathAnnotation.java
@@ -263,7 +263,6 @@ public class PathAnnotation {
                        this.schema = b.schema;
                        this.serializer = b.serializer;
                        this.value = b.value;
-                       postConstruct();
                }
 
                @Override /* Overridden from Path */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/PathRemainderAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/PathRemainderAnnotation.java
index 8d41ee709c..edb968d1ef 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/PathRemainderAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/PathRemainderAnnotation.java
@@ -243,7 +243,6 @@ public class PathRemainderAnnotation {
                        this.parser = b.parser;
                        this.schema = b.schema;
                        this.serializer = b.serializer;
-                       postConstruct();
                }
 
                @Override /* Overridden from PathRemainder */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/QueryAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/QueryAnnotation.java
index 0604f07773..711af52eed 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/QueryAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/QueryAnnotation.java
@@ -262,7 +262,6 @@ public class QueryAnnotation {
                        this.serializer = b.serializer;
                        this.value = b.value;
                        this.def = b.def;
-                       postConstruct();
                }
 
                @Override /* Overridden from Query */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/RequestAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/RequestAnnotation.java
index 5f3db9923e..3116181f00 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/RequestAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/RequestAnnotation.java
@@ -178,7 +178,6 @@ public class RequestAnnotation {
                        this.description = copyOf(b.description);
                        this.parser = b.parser;
                        this.serializer = b.serializer;
-                       postConstruct();
                }
 
                @Override /* Overridden from Request */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseAnnotation.java
index 7103bcc5b1..b079047dec 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/ResponseAnnotation.java
@@ -234,7 +234,6 @@ public class ResponseAnnotation {
                        this.parser = b.parser;
                        this.schema = b.schema;
                        this.serializer = b.serializer;
-                       postConstruct();
                }
 
                @Override /* Overridden from Response */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/StatusCodeAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/StatusCodeAnnotation.java
index 01f676894a..0849af4d61 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/StatusCodeAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/StatusCodeAnnotation.java
@@ -177,7 +177,6 @@ public class StatusCodeAnnotation {
                        super(b);
                        this.description = copyOf(b.description);
                        this.value = Arrays.copyOf(b.value, b.value.length);
-                       postConstruct();
                }
 
                @Override /* Overridden from Response */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/TagAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/TagAnnotation.java
index 465994a716..84930b3463 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/TagAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/TagAnnotation.java
@@ -103,7 +103,6 @@ public class TagAnnotation {
                        this.description = copyOf(b.description);
                        this.externalDocs = b.externalDocs;
                        this.name = b.name;
-                       postConstruct();
                }
 
                @Override /* Overridden from Tag */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/annotation/JsonAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/annotation/JsonAnnotation.java
index de2eebc25f..c5b7de7b8c 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/annotation/JsonAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/annotation/JsonAnnotation.java
@@ -191,7 +191,6 @@ public class JsonAnnotation {
                        super(b);
                        this.description = copyOf(b.description);
                        this.wrapperAttr = b.wrapperAttr;
-                       postConstruct();
                }
 
                @Override /* Overridden from Json */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/annotation/MsgPackAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/annotation/MsgPackAnnotation.java
index 98eb7a7d8b..869e55c521 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/annotation/MsgPackAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/annotation/MsgPackAnnotation.java
@@ -177,7 +177,6 @@ public class MsgPackAnnotation {
                Object(MsgPackAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from annotation */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/annotation/OpenApiAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/annotation/OpenApiAnnotation.java
index c8649db73d..98fc430344 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/annotation/OpenApiAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/annotation/OpenApiAnnotation.java
@@ -177,7 +177,6 @@ public class OpenApiAnnotation {
                Object(OpenApiAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from annotation */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/annotation/PlainTextAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/annotation/PlainTextAnnotation.java
index a587ac818e..a77d96c1e3 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/annotation/PlainTextAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/annotation/PlainTextAnnotation.java
@@ -174,7 +174,6 @@ public class PlainTextAnnotation {
                Object(PlainTextAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from annotation */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/annotation/SoapXmlAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/annotation/SoapXmlAnnotation.java
index 18c215aef2..b6e1e2fccd 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/annotation/SoapXmlAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/annotation/SoapXmlAnnotation.java
@@ -174,7 +174,6 @@ public class SoapXmlAnnotation {
                Object(SoapXmlAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from annotation */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/annotation/UonAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/annotation/UonAnnotation.java
index 24cfd800e8..c3e8be2c1e 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/annotation/UonAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/annotation/UonAnnotation.java
@@ -177,7 +177,6 @@ public class UonAnnotation {
                Object(UonAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from annotation */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/annotation/UrlEncodingAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/annotation/UrlEncodingAnnotation.java
index b26479324c..c549462425 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/annotation/UrlEncodingAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/annotation/UrlEncodingAnnotation.java
@@ -191,7 +191,6 @@ public class UrlEncodingAnnotation {
                        super(b);
                        this.description = copyOf(b.description);
                        this.expandedParams = b.expandedParams;
-                       postConstruct();
                }
 
                @Override /* Overridden from UrlEncoding */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/annotation/XmlAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/annotation/XmlAnnotation.java
index 244e2de1e0..cf39308892 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/annotation/XmlAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/annotation/XmlAnnotation.java
@@ -229,7 +229,6 @@ public class XmlAnnotation {
                        this.format = b.format;
                        this.namespace = b.namespace;
                        this.prefix = b.prefix;
-                       postConstruct();
                }
 
                @Override /* Overridden from Xml */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/OpSwaggerAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/OpSwaggerAnnotation.java
index 5b304c748b..f83fb9896d 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/OpSwaggerAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/OpSwaggerAnnotation.java
@@ -216,7 +216,6 @@ public class OpSwaggerAnnotation {
                        this.summary = copyOf(b.summary);
                        this.tags = copyOf(b.tags);
                        this.value = copyOf(b.value);
-                       postConstruct();
                }
 
                @Override /* Overridden from OpSwagger */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
index 657ae51b75..c52cbd72f5 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
@@ -821,7 +821,6 @@ public class RestAnnotation {
                        this.headerParams = copyOf(b.headerParams);
                        this.pathParams = copyOf(b.pathParams);
                        this.formDataParams = copyOf(b.formDataParams);
-                       postConstruct();
                }
 
                @Override /* Overridden from Rest */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDeleteAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDeleteAnnotation.java
index 4d02711495..6761c9c639 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDeleteAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDeleteAnnotation.java
@@ -364,7 +364,6 @@ public class RestDeleteAnnotation {
                        this.summary = b.summary;
                        this.swagger = b.swagger;
                        this.value = b.value;
-                       postConstruct();
                }
 
                @Override /* Overridden from RestDelete */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDestroyAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDestroyAnnotation.java
index 1719f703b1..5e1e244d66 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDestroyAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDestroyAnnotation.java
@@ -115,7 +115,6 @@ public class RestDestroyAnnotation {
                Object(RestDestroyAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from RestDestroy */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestEndCallAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestEndCallAnnotation.java
index 2b86d2cfef..05172e5d81 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestEndCallAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestEndCallAnnotation.java
@@ -115,7 +115,6 @@ public class RestEndCallAnnotation {
                Object(RestEndCallAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from RestEndCall */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGetAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGetAnnotation.java
index b9e7643098..fa881cf73a 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGetAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestGetAnnotation.java
@@ -411,7 +411,6 @@ public class RestGetAnnotation {
                        this.summary = b.summary;
                        this.swagger = b.swagger;
                        this.value = b.value;
-                       postConstruct();
                }
 
                @Override /* Overridden from RestGet */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInitAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInitAnnotation.java
index 336cb2c968..3befd939c1 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInitAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInitAnnotation.java
@@ -115,7 +115,6 @@ public class RestInitAnnotation {
                Object(RestInitAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from RestInit */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInjectAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInjectAnnotation.java
index 0eddacfac7..0301229b62 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInjectAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInjectAnnotation.java
@@ -152,7 +152,6 @@ public class RestInjectAnnotation {
                        this.name = b.name;
                        this.value = b.value;
                        this.methodScope = b.methodScope;
-                       postConstruct();
                }
 
                @Override /* Overridden from RestInject */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOpAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOpAnnotation.java
index 2f77628719..81e36f0e38 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOpAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOpAnnotation.java
@@ -505,7 +505,6 @@ public class RestOpAnnotation {
                        this.summary = b.summary;
                        this.swagger = b.swagger;
                        this.value = b.value;
-                       postConstruct();
                }
 
                @Override /* Overridden from RestOp */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOptionsAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOptionsAnnotation.java
index 64270aff47..450848b751 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOptionsAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestOptionsAnnotation.java
@@ -411,7 +411,6 @@ public class RestOptionsAnnotation {
                        this.summary = b.summary;
                        this.swagger = b.swagger;
                        this.value = b.value;
-                       postConstruct();
                }
 
                @Override /* Overridden from RestOptions */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPatchAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPatchAnnotation.java
index 5276feb059..9742485639 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPatchAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPatchAnnotation.java
@@ -478,7 +478,6 @@ public class RestPatchAnnotation {
                        this.summary = b.summary;
                        this.swagger = b.swagger;
                        this.value = b.value;
-                       postConstruct();
                }
 
                @Override /* Overridden from RestPatch */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostAnnotation.java
index 8c585ff11e..49a470772c 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostAnnotation.java
@@ -479,7 +479,6 @@ public class RestPostAnnotation {
                        this.summary = b.summary;
                        this.swagger = b.swagger;
                        this.value = b.value;
-                       postConstruct();
                }
 
                @Override /* Overridden from RestPost */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostCallAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostCallAnnotation.java
index 7191d03d0f..7018189514 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostCallAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostCallAnnotation.java
@@ -115,7 +115,6 @@ public class RestPostCallAnnotation {
                Object(RestPostCallAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from RestPostCall */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostInitAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostInitAnnotation.java
index af86c5a1f6..6a4c95d6a2 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostInitAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostInitAnnotation.java
@@ -128,7 +128,6 @@ public class RestPostInitAnnotation {
                        super(b);
                        this.description = copyOf(b.description);
                        this.childFirst = b.childFirst;
-                       postConstruct();
                }
 
                @Override /* Overridden from RestHook */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPreCallAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPreCallAnnotation.java
index 15552d236e..df872170e0 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPreCallAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPreCallAnnotation.java
@@ -115,7 +115,6 @@ public class RestPreCallAnnotation {
                Object(RestPreCallAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from RestPreCall */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPutAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPutAnnotation.java
index b7af31cf62..4204f6e464 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPutAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPutAnnotation.java
@@ -479,7 +479,6 @@ public class RestPutAnnotation {
                        this.summary = b.summary;
                        this.swagger = b.swagger;
                        this.value = b.value;
-                       postConstruct();
                }
 
                @Override /* Overridden from RestPut */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestStartCallAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestStartCallAnnotation.java
index c4e8a06113..049a83d3e9 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestStartCallAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestStartCallAnnotation.java
@@ -115,7 +115,6 @@ public class RestStartCallAnnotation {
                Object(RestStartCallAnnotation.Builder b) {
                        super(b);
                        this.description = copyOf(b.description);
-                       postConstruct();
                }
 
                @Override /* Overridden from RestStartCall */
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/SwaggerAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/SwaggerAnnotation.java
index df13e6672e..5daafcd674 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/SwaggerAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/SwaggerAnnotation.java
@@ -187,7 +187,6 @@ public class SwaggerAnnotation {
                        this.title = copyOf(b.title);
                        this.value = copyOf(b.value);
                        this.version = b.version;
-                       postConstruct();
                }
 
                @Override /* Overridden from Swagger */
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/common/annotation/AnnotationObject_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/common/annotation/AnnotationObject_Test.java
index 5c31088508..57c3e300e3 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/common/annotation/AnnotationObject_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/common/annotation/AnnotationObject_Test.java
@@ -94,7 +94,6 @@ class AnnotationObject_Test extends TestBase {
                        this.number = b.number;
                        this.flag = b.flag;
                        this.array = Arrays.copyOf(b.array, b.array.length);
-                       postConstruct();
                }
 
                @Override
@@ -294,31 +293,16 @@ class AnnotationObject_Test extends TestBase {
        }
 
        
//------------------------------------------------------------------------------------------------------------------
-       // postConstruct() requirement tests
+       // Constructor validation tests
        
//------------------------------------------------------------------------------------------------------------------
 
        @Test
-       void e01_postConstruct_required() {
-               // Test that hashCode() throws exception if postConstruct() was 
not called
-               var obj = new AnnotationObject(new 
AnnotationObject.Builder(TestAnnotation.class)) {
-                       // Intentionally not calling postConstruct()
-               };
-
+       void e01_constructor_nullAnnotationType() {
                var e = assertThrows(IllegalArgumentException.class, () -> {
-                       obj.hashCode();
+                       new AnnotationObject.Builder(null);
                });
 
-               assertTrue(e.getMessage().contains("postConstruct"));
-       }
-
-       @Test
-       void e02_postConstruct_called() {
-               // Test that hashCode() works correctly when postConstruct() is 
called
-               var a = TestAnnotationObject.create().build();
-
-               // Should not throw exception and should have valid hashcode
-               assertNotEquals(-1, a.hashCode());
-               assertNotEquals(0, a.hashCode());
+               assertTrue(e.getMessage().contains("annotationType"));
        }
 
        
//------------------------------------------------------------------------------------------------------------------
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/common/annotation/AppliedAnnotationObject_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/common/annotation/AppliedAnnotationObject_Test.java
new file mode 100644
index 0000000000..81da56105d
--- /dev/null
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/common/annotation/AppliedAnnotationObject_Test.java
@@ -0,0 +1,694 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau.common.annotation;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.common.reflect.*;
+import org.junit.jupiter.api.*;
+
+class AppliedAnnotationObject_Test extends TestBase {
+
+       private static final String CNAME = 
AppliedAnnotationObject_Test.class.getName();
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Test annotation for testing purposes
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, 
ElementType.CONSTRUCTOR})
+       @Retention(RetentionPolicy.RUNTIME)
+       public @interface TestAppliedAnnotation {
+               String[] on() default {};
+               String value() default "";
+               int number() default 0;
+       }
+
+       /**
+        * Implementation of TestAppliedAnnotation using 
AppliedAnnotationObject with basic Builder
+        */
+       public static class TestAppliedAnnotationObject extends 
AppliedAnnotationObject implements TestAppliedAnnotation {
+
+               private final String value;
+               private final int number;
+
+               public static class Builder extends 
AppliedAnnotationObject.Builder {
+                       String value = "";
+                       int number = 0;
+
+                       public Builder() {
+                               super(TestAppliedAnnotation.class);
+                       }
+
+                       public Builder value(String value) {
+                               this.value = value;
+                               return this;
+                       }
+
+                       public Builder number(int number) {
+                               this.number = number;
+                               return this;
+                       }
+
+                       @Override
+                       public Builder on(String...value) {
+                               super.on(value);
+                               return this;
+                       }
+
+                       public TestAppliedAnnotation build() {
+                               return new TestAppliedAnnotationObject(this);
+                       }
+               }
+
+               public static Builder create() {
+                       return new Builder();
+               }
+
+               public TestAppliedAnnotationObject(Builder b) {
+                       super(b);
+                       this.value = b.value;
+                       this.number = b.number;
+               }
+
+               @Override
+               public String value() {
+                       return value;
+               }
+
+               @Override
+               public int number() {
+                       return number;
+               }
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Test classes for targeting
+       
//------------------------------------------------------------------------------------------------------------------
+
+       public static class TargetClass1 {
+               public String field1;
+               public int field2;
+
+               public TargetClass1() {}
+               public TargetClass1(String s) {}
+
+               public void method1() {}
+               public String method2(int x) { return null; }
+       }
+
+       public static class TargetClass2 {}
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Basic tests - on() with strings
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test
+       void a01_basic_noTargets() {
+               var a = TestAppliedAnnotationObject.create().build();
+               assertArrayEquals(new String[0], a.on());
+       }
+
+       @Test
+       void a02_basic_singleTarget() {
+               var a = TestAppliedAnnotationObject.create()
+                       .on("com.example.MyClass")
+                       .build();
+
+               assertArrayEquals(new String[]{"com.example.MyClass"}, a.on());
+       }
+
+       @Test
+       void a03_basic_multipleTargets() {
+               var a = TestAppliedAnnotationObject.create()
+                       .on("com.example.Class1")
+                       .on("com.example.Class2")
+                       .build();
+
+               assertArrayEquals(new String[]{"com.example.Class1", 
"com.example.Class2"}, a.on());
+       }
+
+       @Test
+       void a04_basic_varargsTargets() {
+               var a = TestAppliedAnnotationObject.create()
+                       .on("target1", "target2", "target3")
+                       .build();
+
+               assertArrayEquals(new String[]{"target1", "target2", 
"target3"}, a.on());
+       }
+
+       @Test
+       void a05_basic_withOtherProperties() {
+               var a = TestAppliedAnnotationObject.create()
+                       .on("com.example.MyClass")
+                       .value("test")
+                       .number(42)
+                       .build();
+
+               assertArrayEquals(new String[]{"com.example.MyClass"}, a.on());
+               assertEquals("test", a.value());
+               assertEquals(42, a.number());
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Equality and hashcode tests with on property
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test
+       void b01_equality_sameTargets() {
+               var a1 = TestAppliedAnnotationObject.create()
+                       .on("target1", "target2")
+                       .value("test")
+                       .build();
+
+               var a2 = TestAppliedAnnotationObject.create()
+                       .on("target1", "target2")
+                       .value("test")
+                       .build();
+
+               assertEquals(a1, a2);
+               assertEquals(a1.hashCode(), a2.hashCode());
+       }
+
+       @Test
+       void b02_equality_differentTargets() {
+               var a1 = TestAppliedAnnotationObject.create()
+                       .on("target1")
+                       .build();
+
+               var a2 = TestAppliedAnnotationObject.create()
+                       .on("target2")
+                       .build();
+
+               assertNotEquals(a1, a2);
+       }
+
+       @Test
+       void b03_equality_differentTargetOrder() {
+               // Arrays with different order should not be equal
+               var a1 = TestAppliedAnnotationObject.create()
+                       .on("target1", "target2")
+                       .build();
+
+               var a2 = TestAppliedAnnotationObject.create()
+                       .on("target2", "target1")
+                       .build();
+
+               assertNotEquals(a1, a2);
+       }
+
+       @Test
+       void b04_equality_noTargetsVsWithTargets() {
+               var a1 = TestAppliedAnnotationObject.create().build();
+               var a2 = TestAppliedAnnotationObject.create()
+                       .on("target1")
+                       .build();
+
+               assertNotEquals(a1, a2);
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // BuilderT tests - Class targeting
+       
//------------------------------------------------------------------------------------------------------------------
+
+       /**
+        * Implementation with BuilderT for class targeting
+        */
+       public static class TestAppliedAnnotationObjectT extends 
AppliedAnnotationObject implements TestAppliedAnnotation {
+
+               private final String value;
+
+               public static class Builder extends 
AppliedAnnotationObject.BuilderT {
+                       String value = "";
+
+                       public Builder() {
+                               super(TestAppliedAnnotation.class);
+                       }
+
+                       public Builder value(String value) {
+                               this.value = value;
+                               return this;
+                       }
+
+                       @Override
+                       public Builder on(String...value) {
+                               super.on(value);
+                               return this;
+                       }
+
+                       @Override
+                       public Builder on(Class<?>...value) {
+                               super.on(value);
+                               return this;
+                       }
+
+                       @Override
+                       public Builder on(ClassInfo...value) {
+                               super.on(value);
+                               return this;
+                       }
+
+                       public TestAppliedAnnotation build() {
+                               return new TestAppliedAnnotationObjectT(this);
+                       }
+               }
+
+               public static Builder create() {
+                       return new Builder();
+               }
+
+               public TestAppliedAnnotationObjectT(Builder b) {
+                       super(b);
+                       this.value = b.value;
+               }
+
+               @Override
+               public String value() {
+                       return value;
+               }
+
+               @Override
+               public int number() {
+                       return 0;
+               }
+       }
+
+       @Test
+       void c01_builderT_onClassArray() {
+               var a = TestAppliedAnnotationObjectT.create()
+                       .on(TargetClass1.class, TargetClass2.class)
+                       .build();
+
+               String[] expected = {
+                       CNAME + "$TargetClass1",
+                       CNAME + "$TargetClass2"
+               };
+               assertArrayEquals(expected, a.on());
+       }
+
+       @Test
+       void c02_builderT_onClassInfo() {
+               var ci1 = ClassInfo.of(TargetClass1.class);
+               var ci2 = ClassInfo.of(TargetClass2.class);
+
+               var a = TestAppliedAnnotationObjectT.create()
+                       .on(ci1, ci2)
+                       .build();
+
+               String[] expected = {
+                       CNAME + "$TargetClass1",
+                       CNAME + "$TargetClass2"
+               };
+               assertArrayEquals(expected, a.on());
+       }
+
+       @Test
+       void c03_builderT_mixedTargeting() {
+               var a = TestAppliedAnnotationObjectT.create()
+                       .on("com.example.StringTarget")
+                       .on(TargetClass1.class)
+                       .build();
+
+               String[] expected = {
+                       "com.example.StringTarget",
+                       CNAME + "$TargetClass1"
+               };
+               assertArrayEquals(expected, a.on());
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // BuilderM tests - Method targeting
+       
//------------------------------------------------------------------------------------------------------------------
+
+       /**
+        * Implementation with BuilderM for method targeting
+        */
+       public static class TestAppliedAnnotationObjectM extends 
AppliedAnnotationObject implements TestAppliedAnnotation {
+
+               public static class Builder extends 
AppliedAnnotationObject.BuilderM {
+
+                       public Builder() {
+                               super(TestAppliedAnnotation.class);
+                       }
+
+                       @Override
+                       public Builder on(String...value) {
+                               super.on(value);
+                               return this;
+                       }
+
+                       @Override
+                       public Builder on(Method...value) {
+                               super.on(value);
+                               return this;
+                       }
+
+                       @Override
+                       public Builder on(MethodInfo...value) {
+                               super.on(value);
+                               return this;
+                       }
+
+                       public TestAppliedAnnotation build() {
+                               return new TestAppliedAnnotationObjectM(this);
+                       }
+               }
+
+               public static Builder create() {
+                       return new Builder();
+               }
+
+               public TestAppliedAnnotationObjectM(Builder b) {
+                       super(b);
+               }
+
+               @Override
+               public String value() {
+                       return "";
+               }
+
+               @Override
+               public int number() {
+                       return 0;
+               }
+       }
+
+       @Test
+       void d01_builderM_onMethod() throws Exception {
+               Method m1 = TargetClass1.class.getMethod("method1");
+               Method m2 = TargetClass1.class.getMethod("method2", int.class);
+
+               var a = TestAppliedAnnotationObjectM.create()
+                       .on(m1, m2)
+                       .build();
+
+               String[] expected = {
+                       CNAME + "$TargetClass1.method1()",
+                       CNAME + "$TargetClass1.method2(int)"
+               };
+               assertArrayEquals(expected, a.on());
+       }
+
+       @Test
+       void d02_builderM_onMethodInfo() throws Exception {
+               var mi1 = 
MethodInfo.of(TargetClass1.class.getMethod("method1"));
+               var mi2 = MethodInfo.of(TargetClass1.class.getMethod("method2", 
int.class));
+
+               var a = TestAppliedAnnotationObjectM.create()
+                       .on(mi1, mi2)
+                       .build();
+
+               String[] expected = {
+                       CNAME + "$TargetClass1.method1()",
+                       CNAME + "$TargetClass1.method2(int)"
+               };
+               assertArrayEquals(expected, a.on());
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // BuilderC tests - Constructor targeting
+       
//------------------------------------------------------------------------------------------------------------------
+
+       /**
+        * Implementation with BuilderC for constructor targeting
+        */
+       public static class TestAppliedAnnotationObjectC extends 
AppliedAnnotationObject implements TestAppliedAnnotation {
+
+               public static class Builder extends 
AppliedAnnotationObject.BuilderC {
+
+                       public Builder() {
+                               super(TestAppliedAnnotation.class);
+                       }
+
+                       @Override
+                       public Builder on(String...value) {
+                               super.on(value);
+                               return this;
+                       }
+
+                       @Override
+                       public Builder on(Constructor<?>...value) {
+                               super.on(value);
+                               return this;
+                       }
+
+                       @Override
+                       public Builder on(ConstructorInfo...value) {
+                               super.on(value);
+                               return this;
+                       }
+
+                       public TestAppliedAnnotation build() {
+                               return new TestAppliedAnnotationObjectC(this);
+                       }
+               }
+
+               public static Builder create() {
+                       return new Builder();
+               }
+
+               public TestAppliedAnnotationObjectC(Builder b) {
+                       super(b);
+               }
+
+               @Override
+               public String value() {
+                       return "";
+               }
+
+               @Override
+               public int number() {
+                       return 0;
+               }
+       }
+
+       @Test
+       void e01_builderC_onConstructor() throws Exception {
+               Constructor<?> c1 = TargetClass1.class.getConstructor();
+               Constructor<?> c2 = 
TargetClass1.class.getConstructor(String.class);
+
+               var a = TestAppliedAnnotationObjectC.create()
+                       .on(c1, c2)
+                       .build();
+
+               String[] expected = {
+                       CNAME + "$TargetClass1()",
+                       CNAME + "$TargetClass1(java.lang.String)"
+               };
+               assertArrayEquals(expected, a.on());
+       }
+
+       @Test
+       void e02_builderC_onConstructorInfo() throws Exception {
+               var ci1 = 
ConstructorInfo.of(TargetClass1.class.getConstructor());
+               var ci2 = 
ConstructorInfo.of(TargetClass1.class.getConstructor(String.class));
+
+               var a = TestAppliedAnnotationObjectC.create()
+                       .on(ci1, ci2)
+                       .build();
+
+               String[] expected = {
+                       CNAME + "$TargetClass1()",
+                       CNAME + "$TargetClass1(java.lang.String)"
+               };
+               assertArrayEquals(expected, a.on());
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // BuilderMF tests - Method and Field targeting
+       
//------------------------------------------------------------------------------------------------------------------
+
+       /**
+        * Implementation with BuilderMF for method and field targeting
+        */
+       public static class TestAppliedAnnotationObjectMF extends 
AppliedAnnotationObject implements TestAppliedAnnotation {
+
+               public static class Builder extends 
AppliedAnnotationObject.BuilderMF {
+
+                       public Builder() {
+                               super(TestAppliedAnnotation.class);
+                       }
+
+                       @Override
+                       public Builder on(String...value) {
+                               super.on(value);
+                               return this;
+                       }
+
+                       @Override
+                       public Builder on(Method...value) {
+                               super.on(value);
+                               return this;
+                       }
+
+                       @Override
+                       public Builder on(MethodInfo...value) {
+                               super.on(value);
+                               return this;
+                       }
+
+                       @Override
+                       public Builder on(Field...value) {
+                               super.on(value);
+                               return this;
+                       }
+
+                       @Override
+                       public Builder on(FieldInfo...value) {
+                               super.on(value);
+                               return this;
+                       }
+
+                       public TestAppliedAnnotation build() {
+                               return new TestAppliedAnnotationObjectMF(this);
+                       }
+               }
+
+               public static Builder create() {
+                       return new Builder();
+               }
+
+               public TestAppliedAnnotationObjectMF(Builder b) {
+                       super(b);
+               }
+
+               @Override
+               public String value() {
+                       return "";
+               }
+
+               @Override
+               public int number() {
+                       return 0;
+               }
+       }
+
+       @Test
+       void f01_builderMF_onField() throws Exception {
+               Field f1 = TargetClass1.class.getField("field1");
+               Field f2 = TargetClass1.class.getField("field2");
+
+               var a = TestAppliedAnnotationObjectMF.create()
+                       .on(f1, f2)
+                       .build();
+
+               String[] expected = {
+                       CNAME + "$TargetClass1.field1",
+                       CNAME + "$TargetClass1.field2"
+               };
+               assertArrayEquals(expected, a.on());
+       }
+
+       @Test
+       void f02_builderMF_onFieldInfo() throws Exception {
+               var fi1 = FieldInfo.of(ClassInfo.of(TargetClass1.class), 
TargetClass1.class.getField("field1"));
+               var fi2 = FieldInfo.of(ClassInfo.of(TargetClass1.class), 
TargetClass1.class.getField("field2"));
+
+               var a = TestAppliedAnnotationObjectMF.create()
+                       .on(fi1, fi2)
+                       .build();
+
+               String[] expected = {
+                       CNAME + "$TargetClass1.field1",
+                       CNAME + "$TargetClass1.field2"
+               };
+               assertArrayEquals(expected, a.on());
+       }
+
+       @Test
+       void f03_builderMF_mixedMethodsAndFields() throws Exception {
+               Method m = TargetClass1.class.getMethod("method1");
+               Field f = TargetClass1.class.getField("field1");
+
+               var a = TestAppliedAnnotationObjectMF.create()
+                       .on(m)
+                       .on(f)
+                       .build();
+
+               String[] expected = {
+                       CNAME + "$TargetClass1.method1()",
+                       CNAME + "$TargetClass1.field1"
+               };
+               assertArrayEquals(expected, a.on());
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Fluent API tests
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test
+       void g01_fluentApi_chaining() {
+               var a = TestAppliedAnnotationObject.create()
+                       .on("target1")
+                       .value("test")
+                       .on("target2")
+                       .number(42)
+                       .on("target3")
+                       .build();
+
+               assertArrayEquals(new String[]{"target1", "target2", 
"target3"}, a.on());
+               assertEquals("test", a.value());
+               assertEquals(42, a.number());
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // toMap() tests with on property
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test
+       void h01_toMap_withTargets() {
+               var a = TestAppliedAnnotationObject.create()
+                       .on("target1", "target2")
+                       .value("test")
+                       .build();
+
+               var map = ((TestAppliedAnnotationObject)a).toMap();
+               assertArrayEquals(new String[]{"target1", "target2"}, 
(String[])map.get("on"));
+               assertEquals("test", map.get("value"));
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Edge cases
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test
+       void i01_edgeCase_emptyTargets() {
+               var a = TestAppliedAnnotationObject.create()
+                       .on()
+                       .build();
+
+               assertArrayEquals(new String[0], a.on());
+       }
+
+       @Test
+       void i02_edgeCase_builderReuse() {
+               var builder = TestAppliedAnnotationObject.create()
+                       .on("target1")
+                       .value("test");
+
+               var a1 = builder.build();
+               var a2 = builder.build();
+
+               // Different instances but equal
+               assertNotSame(a1, a2);
+               assertEquals(a1, a2);
+       }
+}
+

Reply via email to