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
commit fc54e2a5e5cb877160d5b16134a977ede3b2949b Author: James Bognar <[email protected]> AuthorDate: Tue May 12 09:35:18 2026 -0400 refactor: extract @BeanConfig from @MarshalledConfig (Phase 3 of bean-layer split) Splits the bean-detection / introspection attributes off of @MarshalledConfig into a new @BeanConfig annotation that lives in juneau-commons (commons.bean), leaving @MarshalledConfig with only marshalling-specific knobs (typePropertyName, dictionary[/_replace], swaps[/_replace], locale, mediaType, timeZone, debug). @BeanConfig in commons.bean is a plain annotation without @ContextApply because commons cannot reference marshall-layer types. Context.CONTEXT_APPLY_FILTER and AnnotationWorkList.applyAnnotation now special-case @BeanConfig and route it to a dedicated BeanConfigAnnotation.Applier in juneau-marshall, which knows how to push the attributes into MarshallingContext.Builder. Callsite migrations: - BasicBeans_Test: @MarshalledConfig(disableIgnoreTransientFields) -> @BeanConfig - DefaultConfig (juneau-rest-server): @MarshalledConfig(ignoreUnknownBeanProperties, ignoreUnknownEnumValues) -> @BeanConfig - MarshalledConfig_Swaps_Test, BasicRestOperations: unchanged (swaps-only). Test files: - MarshalledConfigAnnotation_Test.java trimmed to cover only marshalling attrs. - New BeanConfigAnnotation_Test.java added covering bean-detection attrs. Co-authored-by: Cursor <[email protected]> --- .../apache/juneau/commons/bean/BeanConfig.java} | 361 +---------- .../juneau/commons/bean/BeanConfigAnnotation.java | 39 ++ .../java/org/apache/juneau/AnnotationWorkList.java | 7 + .../src/main/java/org/apache/juneau/Context.java | 9 +- ...igAnnotation.java => BeanConfigAnnotation.java} | 43 +- .../apache/juneau/annotation/MarshalledConfig.java | 720 +-------------------- .../annotation/MarshalledConfigAnnotation.java | 29 - .../apache/juneau/rest/config/DefaultConfig.java | 3 +- .../java/org/apache/juneau/BasicBeans_Test.java | 2 +- ...on_Test.java => BeanConfigAnnotation_Test.java} | 96 +-- .../MarshalledConfigAnnotation_Test.java | 98 +-- 11 files changed, 131 insertions(+), 1276 deletions(-) diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledConfig.java b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanConfig.java similarity index 59% copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledConfig.java copy to juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanConfig.java index e73e65bb5d..d0388ae825 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledConfig.java +++ b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanConfig.java @@ -14,37 +14,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.juneau.annotation; +package org.apache.juneau.commons.bean; -import org.apache.juneau.commons.http.MediaType; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.*; import java.io.*; import java.lang.annotation.*; import java.lang.reflect.*; -import java.util.*; - -import org.apache.juneau.*; -import org.apache.juneau.commons.reflect.Visibility; -import org.apache.juneau.swap.*; -import org.apache.juneau.commons.bean.*; /** - * Annotation for specifying config properties defined in {@link MarshallingContext} and {@link MarshallingTraverseContext}. + * Annotation for specifying bean-modeling config properties on REST classes and methods. + * + * <p> + * The bean-modeling sibling of {@code @MarshalledConfig}. + * Where {@code @MarshalledConfig} (in <c>juneau-marshall</c>) carries the marshalling-only attributes + * (such as {@code dictionary}, {@code swaps}, {@code typePropertyName}, {@code locale}, {@code mediaType}, + * and {@code timeZone}), this annotation carries the attributes that describe how the bean MODEL is + * detected and introspected — visibility settings, required-properties toggles, fluent-setter detection, + * property naming, not-bean exclusions, etc. * * <p> - * Used primarily for specifying marshalling configuration properties on REST classes and methods. + * Splitting the annotations lets a class/method participate in bean-modeling configuration without + * dragging in any marshalling concerns, and lets the bean-modeling layer live in <c>juneau-commons</c> + * independent of <c>juneau-marshall</c>. * + * <p> + * Can be used in the following locations: + * <ul> + * <li>Classes and methods (typically REST classes/methods). + * </ul> */ +@Documented @Target({ TYPE, METHOD }) @Retention(RUNTIME) @Inherited -@ContextApply(MarshalledConfigAnnotation.Applier.class) @SuppressWarnings({ "java:S100" // Annotation methods use underscore suffix to avoid Java keyword conflicts }) -public @interface MarshalledConfig { +public @interface BeanConfig { /** * Minimum bean class visibility. @@ -69,10 +77,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beanClassVisibility(Visibility)} - * </ul> - * * @return The annotation value. */ String beanClassVisibility() default ""; @@ -100,10 +104,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beanConstructorVisibility(Visibility)} - * </ul> - * * @return The annotation value. */ String beanConstructorVisibility() default ""; @@ -131,10 +131,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beanFieldVisibility(Visibility)} - * </ul> - * * @return The annotation value. */ String beanFieldVisibility() default ""; @@ -143,8 +139,7 @@ public @interface MarshalledConfig { * BeanMap.put() returns old property value. * * <p> - * If <js>"true"</js>, then the {@link BeanMap#put(String,Object) BeanMap.put()} method will return old property - * values. + * If <js>"true"</js>, then the {@code BeanMap.put()} method will return old property values. * <br>Otherwise, it returns <jk>null</jk>. * * <ul class='values'> @@ -157,10 +152,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beanMapPutReturnsOldValue()} - * </ul> - * * @return The annotation value. */ String beanMapPutReturnsOldValue() default ""; @@ -188,10 +179,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beanMethodVisibility(Visibility)} - * </ul> - * * @return The annotation value. */ String beanMethodVisibility() default ""; @@ -211,12 +198,6 @@ public @interface MarshalledConfig { * <h5 class='section'>Notes:</h5><ul> * <li class='note'> * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * <li class='note'> - * The {@link Bean @Marshalled} annotation can be used on a class to override this setting when <js>"true"</js>. - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beansRequireDefaultConstructor()} * </ul> * * @return The annotation value. @@ -238,12 +219,6 @@ public @interface MarshalledConfig { * <h5 class='section'>Notes:</h5><ul> * <li class='note'> * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * <li class='note'> - * The {@link Bean @Marshalled} annotation can be used on a class to override this setting when <js>"true"</js>. - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beansRequireSerializable()} * </ul> * * @return The annotation value. @@ -267,98 +242,10 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beansRequireSettersForGetters()} - * </ul> - * * @return The annotation value. */ String beansRequireSettersForGetters() default ""; - /** - * Debug mode. - * - * <p> - * Enables the following additional information during serialization: - * <ul class='spaced-list'> - * <li> - * When bean getters throws exceptions, the exception includes the object stack information - * in order to determine how that method was invoked. - * <li> - * Enables {@link org.apache.juneau.MarshallingTraverseContext.Builder#detectRecursions()}. - * </ul> - * - * <p> - * Enables the following additional information during parsing: - * <ul class='spaced-list'> - * <li> - * When bean setters throws exceptions, the exception includes the object stack information - * in order to determine how that method was invoked. - * </ul> - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.Context.Builder#debug()} - * </ul> - * - * @return The annotation value. - */ - String debug() default ""; - - /** - * Bean dictionary. - * - * <p> - * The list of classes that make up the bean dictionary in this bean context. - * - * <p> - * A dictionary is a name/class mapping used to find class types during parsing when they cannot be inferred - * through reflection. - * <br>The names are defined through the {@link Bean#typeName() @Marshalled(typeName)} annotation defined on the bean class. - * <br>For example, if a class <c>Foo</c> has a type-name of <js>"myfoo"</js>, then it would end up serialized - * as <js>"{_type:'myfoo',...}"</js>. - * - * <p> - * This setting tells the parsers which classes to look for when resolving <js>"_type"</js> attributes. - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='ja'>{@link Bean#dictionary()} - * <li class='ja'>{@link MarshalledProp#dictionary()} - * <li class='ja'>{@link MarshalledConfig#dictionary_replace()} - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beanDictionary(Class...)} - * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/BeanDictionaryBasics">Bean Dictionary Basics</a> - * </ul> - * - * @return The annotation value. - */ - Class<?>[] dictionary() default {}; - - /** - * Replace bean dictionary. - * - * <p> - * Same as {@link #dictionary()} but replaces any existing value. - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='ja'>{@link Bean#dictionary()} - * <li class='ja'>{@link MarshalledProp#dictionary()} - * <li class='ja'>{@link MarshalledConfig#dictionary()} - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beanDictionary(Class...)} - * </ul> - * - * @return The annotation value. - */ - Class<?>[] dictionary_replace() default {}; - /** * Beans don't require at least one property. * @@ -376,10 +263,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#disableBeansRequireSomeProperties()} - * </ul> - * * @return The annotation value. */ String disableBeansRequireSomeProperties() default ""; @@ -401,10 +284,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#disableIgnoreMissingSetters()} - * </ul> - * * @return The annotation value. */ String disableIgnoreMissingSetters() default ""; @@ -425,10 +304,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#disableIgnoreTransientFields()} - * </ul> - * * @return The annotation value. */ String disableIgnoreTransientFields() default ""; @@ -450,10 +325,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#disableIgnoreUnknownNullBeanProperties()} - * </ul> - * * @return The annotation value. */ String disableIgnoreUnknownNullBeanProperties() default ""; @@ -476,10 +347,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#disableInterfaceProxies()} - * </ul> - * * @return The annotation value. */ String disableInterfaceProxies() default ""; @@ -510,8 +377,7 @@ public @interface MarshalledConfig { * </ul> * * <h5 class='section'>See Also:</h5><ul> - * <li class='ja'>{@link Bean#findFluentSetters()} - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#findFluentSetters()} + * <li class='ja'>{@link BeanType#findFluentSetters()} * </ul> * * @return The annotation value. @@ -535,10 +401,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#ignoreInvocationExceptionsOnGetters()} - * </ul> - * * @return The annotation value. */ String ignoreInvocationExceptionsOnGetters() default ""; @@ -560,10 +422,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#ignoreInvocationExceptionsOnSetters()} - * </ul> - * * @return The annotation value. */ String ignoreInvocationExceptionsOnSetters() default ""; @@ -585,10 +443,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#ignoreUnknownBeanProperties()} - * </ul> - * * @return The annotation value. */ String ignoreUnknownBeanProperties() default ""; @@ -609,10 +463,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#ignoreUnknownEnumValues()} - * </ul> - * * @return The annotation value. */ String ignoreUnknownEnumValues() default ""; @@ -636,7 +486,7 @@ public @interface MarshalledConfig { * } * * <jc>// Apply it to a config</jc> - * <ja>@MarshalledConfig</ja>( + * <ja>@BeanConfig</ja>( * interfaces={ * A.<jk>class</jk> * } @@ -648,53 +498,13 @@ public @interface MarshalledConfig { * individually on the child classes. * * <h5 class='section'>Notes:</h5><ul> - * <li class='note'>The {@link Bean#interfaceClass() @Marshalled(interfaceClass)} annotation is the equivalent annotation-based solution. + * <li class='note'>The {@link BeanType#interfaceClass() @BeanType(interfaceClass)} annotation is the equivalent annotation-based solution. * </ul> * * @return The annotation value. */ Class<?>[] interfaces() default {}; - /** - * Locale. - * - * <p> - * Specifies the default locale for serializer and parser sessions. - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingSession.Builder#locale(Locale)} - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#locale(Locale)} - * </ul> - * - * @return The annotation value. - */ - String locale() default ""; - - /** - * Media type. - * - * <p> - * Specifies the default media type value for serializer and parser sessions. - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingSession.Builder#mediaType(MediaType)} - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#mediaType(MediaType)} - * </ul> - * - * @return The annotation value. - */ - String mediaType() default ""; - /** * Bean class exclusions. * @@ -707,11 +517,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='ja'>{@link MarshalledIgnore} - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#notBeanClasses(Class...)} - * </ul> - * * @return The annotation value. */ Class<?>[] notBeanClasses() default {}; @@ -722,10 +527,6 @@ public @interface MarshalledConfig { * <p> * Same as {@link #notBeanClasses()} but replaces any existing value. * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#notBeanClasses(Class...)} - * </ul> - * * @return The annotation value. */ Class<?>[] notBeanClasses_replace() default {}; @@ -759,10 +560,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#notBeanPackages(String...)} - * </ul> - * * @return The annotation value. */ String[] notBeanPackages() default {}; @@ -773,10 +570,6 @@ public @interface MarshalledConfig { * <p> * Same as {@link #notBeanPackages()} but replaces any existing value. * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#notBeanPackages(String...)} - * </ul> - * * @return The annotation value. */ String[] notBeanPackages_replace() default {}; @@ -795,10 +588,6 @@ public @interface MarshalledConfig { * <li>{@link PropertyNamerULC} - Dashed-upper-case names. * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#propertyNamer(Class)} - * </ul> - * * @return The annotation value. */ Class<? extends PropertyNamer> propertyNamer() default PropertyNamer.Void.class; @@ -829,100 +618,10 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#unsortedProperties()} - * </ul> - * * @return The annotation value. */ String unsortedProperties() default ""; - /** - * Java object swaps. - * - * <p> - * Swaps are used to "swap out" non-serializable classes with serializable equivalents during serialization, - * and "swap in" the non-serializable class during parsing. - * - * <p> - * An example of a swap would be a <c>Calendar</c> object that gets swapped out for an ISO8601 string. - * - * <p> - * Multiple swaps can be associated with a single class. - * <br>When multiple swaps are applicable to the same class, the media type pattern defined by - * {@link ObjectSwap#forMediaTypes()} or {@link Swap#mediaTypes() @Swap(mediaTypes)} are used to come up with the best match. - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#swaps(Class...)} - * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SwapBasics">Swap Basics</a> - * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/PerMediaTypeSwaps">Per-media-type Swaps</a> - * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/OneWaySwaps">One-way Swaps</a> - * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SwapAnnotation">@Swap Annotation</a> - * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/AutoSwaps">Auto-detected swaps</a> - * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SurrogateClasses">Surrogate Classes</a> - * </ul> - * - * @return The annotation value. - */ - Class<?>[] swaps() default {}; - - /** - * Replace Java object swap classes. - * - * <p> - * Same as {@link #swaps()} but replaces any existing value. - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#swaps(Class...)} - * </ul> - * - * @return The annotation value. - */ - Class<?>[] swaps_replace() default {}; - - /** - * Time zone. - * - * <p> - * Specifies the default timezone for serializer and parser sessions. - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingSession.Builder#timeZone(TimeZone)} - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#timeZone(TimeZone)} - * </ul> - * - * @return The annotation value. - */ - String timeZone() default ""; - - /** - * Bean type property name. - * - * <p> - * This specifies the name of the bean property used to store the dictionary name of a bean type so that the - * parser knows the data type to reconstruct. - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Default value: <js>"_type"</js>. - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='ja'>{@link Bean#typePropertyName()} - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#typePropertyName(String)} - * </ul> - * - * @return The annotation value. - */ - String typePropertyName() default ""; - /** * Use enum names. * @@ -939,10 +638,6 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#useEnumNames()} - * </ul> - * * @return The annotation value. */ String useEnumNames() default ""; @@ -952,7 +647,7 @@ public @interface MarshalledConfig { * * <p> * Using the built-in Java bean introspector will not pick up fields or non-standard getters/setters. - * <br>Most {@link Bean @Marshalled} annotations will be ignored. + * <br>Most {@link BeanType @BeanType} annotations will be ignored. * * <ul class='values'> * <li><js>"true"</js> @@ -964,11 +659,7 @@ public @interface MarshalledConfig { * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). * </ul> * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#useJavaBeanIntrospector()} - * </ul> - * * @return The annotation value. */ String useJavaBeanIntrospector() default ""; -} \ No newline at end of file +} diff --git a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanConfigAnnotation.java b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanConfigAnnotation.java new file mode 100644 index 0000000000..17b9c33991 --- /dev/null +++ b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanConfigAnnotation.java @@ -0,0 +1,39 @@ +/* + * 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.commons.bean; + +/** + * Utility classes and methods for the {@link BeanConfig @BeanConfig} annotation. + * + * <p> + * This class is intentionally a metadata-only placeholder in the bean-modeling layer. + * The actual application logic that pushes {@link BeanConfig @BeanConfig} attributes into a + * marshalling context builder lives in {@code juneau-marshall} (in the sibling + * {@code org.apache.juneau.annotation.BeanConfigAnnotation.Applier} class), since + * {@code juneau-commons} cannot depend on {@code juneau-marshall}. + * + * <h5 class='section'>See Also:</h5><ul> + * <li class='ja'>{@link BeanConfig} + * </ul> + */ +public class BeanConfigAnnotation { + + /** + * Prevents instantiation. + */ + private BeanConfigAnnotation() {} +} diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/AnnotationWorkList.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/AnnotationWorkList.java index a46bb868b6..145d76a98d 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/AnnotationWorkList.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/AnnotationWorkList.java @@ -25,6 +25,7 @@ import java.util.*; import java.util.stream.*; import org.apache.juneau.annotation.*; +import org.apache.juneau.commons.bean.BeanConfig; import org.apache.juneau.commons.reflect.*; import org.apache.juneau.svl.*; @@ -131,6 +132,12 @@ public class AnnotationWorkList extends ArrayList<AnnotationWork> { }) private void applyAnnotation(AnnotationInfo<?> ai) { var a = ai.inner(); + // Special-case @BeanConfig from juneau-commons. The annotation cannot reference @ContextApply + // (which lives in juneau-marshall), so we route it to its Applier directly. + if (a.annotationType() == BeanConfig.class) { + add(ai, (AnnotationApplier<Annotation,Object>)(AnnotationApplier<?,?>) new BeanConfigAnnotation.Applier(vrs)); + return; + } var cpa = assertNotNull(a.annotationType().getAnnotation(ContextApply.class), "Annotation found without @ContextApply: %s", cn(ai.annotationType())); Arrays.stream(cpa.value()) .map(x -> safe(() -> (Constructor<? extends AnnotationApplier<?,?>>)x.getConstructor(VarResolverSession.class))) diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java index 9c51445e85..87f4496858 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java @@ -29,6 +29,7 @@ import java.util.function.*; import org.apache.juneau.annotation.*; import org.apache.juneau.bson.annotation.BsonConfig; import org.apache.juneau.cbor.annotation.CborConfig; +import org.apache.juneau.commons.bean.BeanConfig; import org.apache.juneau.commons.collections.*; import org.apache.juneau.commons.reflect.*; import org.apache.juneau.commons.utils.*; @@ -877,8 +878,14 @@ public abstract class Context { /** * Predicate for annotations that themselves are annotated with {@link ContextApply}. + * + * <p> + * Also matches {@link BeanConfig} from {@code juneau-commons}, which intentionally lacks a + * {@link ContextApply @ContextApply} meta-annotation because {@code juneau-commons} cannot reference + * marshall-layer types. {@link AnnotationWorkList} routes {@link BeanConfig} to its + * {@link BeanConfigAnnotation.Applier} via an explicit special case. */ - public static final Predicate<AnnotationInfo<?>> CONTEXT_APPLY_FILTER = x -> x.hasAnnotation(ContextApply.class); + public static final Predicate<AnnotationInfo<?>> CONTEXT_APPLY_FILTER = x -> x.hasAnnotation(ContextApply.class) || x.annotationType() == BeanConfig.class; /** * Instantiates a builder of the specified context class. diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledConfigAnnotation.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanConfigAnnotation.java similarity index 72% copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledConfigAnnotation.java copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanConfigAnnotation.java index c5708159ce..9960d212ba 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledConfigAnnotation.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanConfigAnnotation.java @@ -16,31 +16,41 @@ */ package org.apache.juneau.annotation; -import org.apache.juneau.commons.http.MediaType; import static org.apache.juneau.commons.utils.CollectionUtils.*; -import java.util.*; - import org.apache.juneau.*; import org.apache.juneau.commons.bean.*; import org.apache.juneau.commons.reflect.*; import org.apache.juneau.svl.*; /** - * Utility classes and methods for the {@link MarshalledConfig @MarshalledConfig} annotation. + * Utility classes and methods for the {@link BeanConfig @BeanConfig} annotation. + * + * <p> + * Houses the {@link Applier} that pushes {@link BeanConfig @BeanConfig} attributes into a + * {@link org.apache.juneau.MarshallingContext.Builder}. The annotation itself lives in + * {@code juneau-commons} (in {@link org.apache.juneau.commons.bean.BeanConfig}), but + * the application logic lives here in {@code juneau-marshall} because it depends on + * marshall-layer types ({@link AnnotationApplier}, {@link MarshallingContext.Builder}, + * {@link VarResolverSession}, etc.). * + * <p> + * Because {@link BeanConfig @BeanConfig} cannot carry a {@link ContextApply @ContextApply} + * meta-annotation (that annotation lives in {@code juneau-marshall} and cannot be referenced + * from {@code juneau-commons}), {@link AnnotationWorkList} special-cases the + * {@link BeanConfig} annotation type and instantiates this {@link Applier} directly. */ -public class MarshalledConfigAnnotation { +public class BeanConfigAnnotation { /** * Prevents instantiation. */ - private MarshalledConfigAnnotation() {} + private BeanConfigAnnotation() {} /** - * Applies {@link MarshalledConfig} annotations to a {@link org.apache.juneau.MarshallingContext.Builder}. + * Applies {@link BeanConfig} annotations to a {@link org.apache.juneau.MarshallingContext.Builder}. */ - public static class Applier extends AnnotationApplier<MarshalledConfig,MarshallingContext.Builder> { + public static class Applier extends AnnotationApplier<BeanConfig,MarshallingContext.Builder> { /** * Constructor. @@ -48,12 +58,12 @@ public class MarshalledConfigAnnotation { * @param vr The resolver for resolving values in annotations. */ public Applier(VarResolverSession vr) { - super(MarshalledConfig.class, MarshallingContext.Builder.class, vr); + super(BeanConfig.class, MarshallingContext.Builder.class, vr); } @Override - public void apply(AnnotationInfo<MarshalledConfig> ai, MarshallingContext.Builder b) { - MarshalledConfig a = ai.inner(); + public void apply(AnnotationInfo<BeanConfig> ai, MarshallingContext.Builder b) { + BeanConfig a = ai.inner(); // @formatter:off string(a.beanClassVisibility()).map(Visibility::valueOf).ifPresent(b::beanClassVisibility); @@ -65,7 +75,6 @@ public class MarshalledConfigAnnotation { bool(a.beansRequireSerializable()).ifPresent(b::beansRequireSerializable); bool(a.beansRequireSettersForGetters()).ifPresent(b::beansRequireSettersForGetters); bool(a.disableBeansRequireSomeProperties()).ifPresent(b::disableBeansRequireSomeProperties); - bool(a.debug()).ifPresent(b::debug); bool(a.findFluentSetters()).ifPresent(b::findFluentSetters); bool(a.ignoreInvocationExceptionsOnGetters()).ifPresent(b::ignoreInvocationExceptionsOnGetters); bool(a.ignoreInvocationExceptionsOnSetters()).ifPresent(b::ignoreInvocationExceptionsOnSetters); @@ -78,14 +87,6 @@ public class MarshalledConfigAnnotation { bool(a.useEnumNames()).ifPresent(b::useEnumNames); bool(a.disableInterfaceProxies()).ifPresent(b::disableInterfaceProxies); bool(a.useJavaBeanIntrospector()).ifPresent(b::useJavaBeanIntrospector); - string(a.typePropertyName()).ifPresent(b::typePropertyName); - string(a.locale()).map(Locale::forLanguageTag).ifPresent(b::locale); - string(a.mediaType()).map(MediaType::of).ifPresent(b::mediaType); - string(a.timeZone()).map(TimeZone::getTimeZone).ifPresent(b::timeZone); - classes(a.dictionary()).ifPresent(b::beanDictionary); - classes(a.dictionary_replace()).ifPresent(x -> { b.beanDictionary().clear(); b.beanDictionary(x);}); - classes(a.swaps()).ifPresent(b::swaps); - classes(a.swaps_replace()).ifPresent(x -> { b.swaps().clear(); b.swaps(x);}); classes(a.notBeanClasses()).ifPresent(b::notBeanClasses); classes(a.notBeanClasses_replace()).ifPresent(x -> { b.notBeanClasses().clear(); b.notBeanClasses(x);}); type(a.propertyNamer()).ifPresent(b::propertyNamer); @@ -95,4 +96,4 @@ public class MarshalledConfigAnnotation { // @formatter:on } } -} \ No newline at end of file +} diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledConfig.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledConfig.java index e73e65bb5d..aec1ef5fda 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledConfig.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledConfig.java @@ -20,22 +20,24 @@ import org.apache.juneau.commons.http.MediaType; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.*; -import java.io.*; import java.lang.annotation.*; -import java.lang.reflect.*; import java.util.*; import org.apache.juneau.*; -import org.apache.juneau.commons.reflect.Visibility; import org.apache.juneau.swap.*; -import org.apache.juneau.commons.bean.*; /** - * Annotation for specifying config properties defined in {@link MarshallingContext} and {@link MarshallingTraverseContext}. + * Annotation for specifying marshalling-only config properties defined in {@link MarshallingContext} and {@link MarshallingTraverseContext}. * * <p> * Used primarily for specifying marshalling configuration properties on REST classes and methods. * + * <p> + * This annotation is the marshalling-only sibling of {@code @BeanConfig}. After the Phase 3 split, + * bean-modeling attributes (visibility settings, fluent-setter detection, property naming, not-bean + * exclusions, etc.) live on {@link org.apache.juneau.commons.bean.BeanConfig @BeanConfig} in + * {@code juneau-commons}. Attributes that affect wire format, type discriminators, swap classes, + * locale/media-type/timezone, and debug mode stay here on {@code @MarshalledConfig}. */ @Target({ TYPE, METHOD }) @Retention(RUNTIME) @@ -46,235 +48,6 @@ import org.apache.juneau.commons.bean.*; }) public @interface MarshalledConfig { - /** - * Minimum bean class visibility. - * - * <p> - * Classes are not considered beans unless they meet the minimum visibility requirements. - * - * <p> - * For example, if the visibility is <c>PUBLIC</c> and the bean class is <jk>protected</jk>, then the class - * will not be interpreted as a bean class and be serialized as a string. - * <br>Use this setting to reduce the visibility requirement. - * - * <ul class='values'> - * <li><js>"PUBLIC"</js> (default) - * <li><js>"PROTECTED"</js> - * <li><js>"DEFAULT"</js> - * <li><js>"PRIVATE"</js> - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beanClassVisibility(Visibility)} - * </ul> - * - * @return The annotation value. - */ - String beanClassVisibility() default ""; - - /** - * Minimum bean constructor visibility. - * - * <p> - * Only look for constructors with the specified minimum visibility. - * - * <p> - * This setting affects the logic for finding no-arg constructors for bean. - * <br>Normally, only <jk>public</jk> no-arg constructors are used. - * <br>Use this setting if you want to reduce the visibility requirement. - * - * <ul class='values'> - * <li><js>"PUBLIC"</js> (default) - * <li><js>"PROTECTED"</js> - * <li><js>"DEFAULT"</js> - * <li><js>"PRIVATE"</js> - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beanConstructorVisibility(Visibility)} - * </ul> - * - * @return The annotation value. - */ - String beanConstructorVisibility() default ""; - - /** - * Minimum bean field visibility. - * - * <p> - * Only look for bean fields with the specified minimum visibility. - * - * <p> - * This affects which fields on a bean class are considered bean properties. - * <br>Normally only <jk>public</jk> fields are considered. - * <br>Use this setting if you want to reduce the visibility requirement. - * - * <ul class='values'> - * <li><js>"PUBLIC"</js> (default) - * <li><js>"PROTECTED"</js> - * <li><js>"DEFAULT"</js> - * <li><js>"PRIVATE"</js> - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beanFieldVisibility(Visibility)} - * </ul> - * - * @return The annotation value. - */ - String beanFieldVisibility() default ""; - - /** - * BeanMap.put() returns old property value. - * - * <p> - * If <js>"true"</js>, then the {@link BeanMap#put(String,Object) BeanMap.put()} method will return old property - * values. - * <br>Otherwise, it returns <jk>null</jk>. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default because it introduces a slight performance penalty during serialization) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beanMapPutReturnsOldValue()} - * </ul> - * - * @return The annotation value. - */ - String beanMapPutReturnsOldValue() default ""; - - /** - * Minimum bean method visibility. - * - * <p> - * Only look for bean methods with the specified minimum visibility. - * - * <p> - * This affects which methods are detected as getters and setters on a bean class. - * <br>Normally only <jk>public</jk> getters and setters are considered. - * <br>Use this setting if you want to reduce the visibility requirement. - * - * <ul class='values'> - * <li><js>"PUBLIC"</js> (default) - * <li><js>"PROTECTED"</js> - * <li><js>"DEFAULT"</js> - * <li><js>"PRIVATE"</js> - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beanMethodVisibility(Visibility)} - * </ul> - * - * @return The annotation value. - */ - String beanMethodVisibility() default ""; - - /** - * Beans require no-arg constructors. - * - * <p> - * If <js>"true"</js>, a Java class must implement a default no-arg constructor to be considered a bean. - * <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * <li class='note'> - * The {@link Bean @Marshalled} annotation can be used on a class to override this setting when <js>"true"</js>. - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beansRequireDefaultConstructor()} - * </ul> - * - * @return The annotation value. - */ - String beansRequireDefaultConstructor() default ""; - - /** - * Beans require Serializable interface. - * - * <p> - * If <js>"true"</js>, a Java class must implement the {@link Serializable} interface to be considered a bean. - * <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * <li class='note'> - * The {@link Bean @Marshalled} annotation can be used on a class to override this setting when <js>"true"</js>. - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beansRequireSerializable()} - * </ul> - * - * @return The annotation value. - */ - String beansRequireSerializable() default ""; - - /** - * Beans require setters for getters. - * - * <p> - * If <js>"true"</js>, only getters that have equivalent setters will be considered as properties on a bean. - * <br>Otherwise, they will be ignored. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#beansRequireSettersForGetters()} - * </ul> - * - * @return The annotation value. - */ - String beansRequireSettersForGetters() default ""; - /** * Debug mode. * @@ -359,302 +132,6 @@ public @interface MarshalledConfig { */ Class<?>[] dictionary_replace() default {}; - /** - * Beans don't require at least one property. - * - * <p> - * If <js>"true"</js>, then a Java class doesn't need to contain at least 1 property to be considered a bean. - * <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#disableBeansRequireSomeProperties()} - * </ul> - * - * @return The annotation value. - */ - String disableBeansRequireSomeProperties() default ""; - - /** - * Don't silently ignore missing setters. - * - * <p> - * If <js>"true"</js>, trying to set a value on a bean property without a setter will throw a {@code BeanRuntimeException}. - * <br>Otherwise it will be sliently ignored. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#disableIgnoreMissingSetters()} - * </ul> - * - * @return The annotation value. - */ - String disableIgnoreMissingSetters() default ""; - - /** - * Don't ignore transient fields. - * - * <p> - * If <jk>true</jk>, methods and fields marked as <jk>transient</jk> will not be ignored as bean properties. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#disableIgnoreTransientFields()} - * </ul> - * - * @return The annotation value. - */ - String disableIgnoreTransientFields() default ""; - - /** - * Don't ignore unknown properties with null values. - * - * <p> - * If <js>"true"</js>, trying to set a <jk>null</jk> value on a non-existent bean property will throw a {@code BeanRuntimeException}. - * Otherwise it will be silently ignored. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#disableIgnoreUnknownNullBeanProperties()} - * </ul> - * - * @return The annotation value. - */ - String disableIgnoreUnknownNullBeanProperties() default ""; - - /** - * Don't use interface proxies. - * - * <p> - * Disables the feature where interfaces will be instantiated as proxy classes through the use of an - * {@link InvocationHandler} if there is no other way of instantiating them. - * <br>Setting this to <js>"true"</js> causes this to be a {@link org.apache.juneau.commons.reflect.BeanRuntimeException}. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#disableInterfaceProxies()} - * </ul> - * - * @return The annotation value. - */ - String disableInterfaceProxies() default ""; - - /** - * Find fluent setters. - * - * <p> - * When enabled, fluent setters are detected on beans. - * - * <p> - * Fluent setters must have the following attributes: - * <ul> - * <li>Public. - * <li>Not static. - * <li>Take in one parameter. - * <li>Return the bean itself. - * </ul> - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='ja'>{@link Bean#findFluentSetters()} - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#findFluentSetters()} - * </ul> - * - * @return The annotation value. - */ - String findFluentSetters() default ""; - - /** - * Ignore invocation errors on getters. - * - * <p> - * If <js>"true"</js>, errors thrown when calling bean getter methods will silently be ignored. - * <br>Otherwise, a {@code BeanRuntimeException} is thrown. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#ignoreInvocationExceptionsOnGetters()} - * </ul> - * - * @return The annotation value. - */ - String ignoreInvocationExceptionsOnGetters() default ""; - - /** - * Ignore invocation errors on setters. - * - * <p> - * If <js>"true"</js>, errors thrown when calling bean setter methods will silently be ignored. - * <br>Otherwise, a {@code BeanRuntimeException} is thrown. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#ignoreInvocationExceptionsOnSetters()} - * </ul> - * - * @return The annotation value. - */ - String ignoreInvocationExceptionsOnSetters() default ""; - - /** - * Ignore unknown properties. - * - * <p> - * If <js>"true"</js>, trying to set a value on a non-existent bean property will silently be ignored. - * <br>Otherwise, a {@code RuntimeException} is thrown. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#ignoreUnknownBeanProperties()} - * </ul> - * - * @return The annotation value. - */ - String ignoreUnknownBeanProperties() default ""; - - /** - * Ignore unknown enum values. - * - * <p> - * If <js>"true"</js>, unknown enum values are set to <jk>null</jk> instead of throwing an exception. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#ignoreUnknownEnumValues()} - * </ul> - * - * @return The annotation value. - */ - String ignoreUnknownEnumValues() default ""; - - /** - * Identifies a set of interfaces. - * - * <p> - * When specified, only the list of properties defined on the interface class will be used during serialization - * of implementation classes. Additional properties on subclasses will be ignored. - * - * <p class='bjava'> - * <jc>// Parent class or interface</jc> - * <jk>public abstract class</jk> A { - * <jk>public</jk> String <jf>foo</jf> = <js>"foo"</js>; - * } - * - * <jc>// Sub class</jc> - * <jk>public class</jk> A1 <jk>extends</jk> A { - * <jk>public</jk> String <jf>bar</jf> = <js>"bar"</js>; - * } - * - * <jc>// Apply it to a config</jc> - * <ja>@MarshalledConfig</ja>( - * interfaces={ - * A.<jk>class</jk> - * } - * ) - * </p> - * - * <p> - * This annotation can be used on the parent class so that it filters to all child classes, or can be set - * individually on the child classes. - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'>The {@link Bean#interfaceClass() @Marshalled(interfaceClass)} annotation is the equivalent annotation-based solution. - * </ul> - * - * @return The annotation value. - */ - Class<?>[] interfaces() default {}; - /** * Locale. * @@ -695,114 +172,6 @@ public @interface MarshalledConfig { */ String mediaType() default ""; - /** - * Bean class exclusions. - * - * <p> - * List of classes that should not be treated as beans even if they appear to be bean-like. - * <br>Not-bean classes are converted to <c>Strings</c> during serialization. - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='ja'>{@link MarshalledIgnore} - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#notBeanClasses(Class...)} - * </ul> - * - * @return The annotation value. - */ - Class<?>[] notBeanClasses() default {}; - - /** - * Replace classes that should not be considered beans. - * - * <p> - * Same as {@link #notBeanClasses()} but replaces any existing value. - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#notBeanClasses(Class...)} - * </ul> - * - * @return The annotation value. - */ - Class<?>[] notBeanClasses_replace() default {}; - - /** - * Bean package exclusions. - * - * <p> - * When specified, the current list of ignore packages are appended to. - * - * <p> - * Any classes within these packages will be serialized to strings using {@link Object#toString()}. - * - * <p> - * Note that you can specify suffix patterns to include all subpackages. - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * The default value excludes the following packages: - * <ul class='compact'> - * <li class='jp'><c>java.lang</c> - * <li class='jp'><c>java.lang.annotation</c> - * <li class='jp'><c>java.lang.ref</c> - * <li class='jp'><c>java.lang.reflect</c> - * <li class='jp'><c>java.io</c> - * <li class='jp'><c>java.net</c> - * <li class='jp'><c>java.nio.*</c> - * <li class='jp'><c>java.util.*</c> - * </ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#notBeanPackages(String...)} - * </ul> - * - * @return The annotation value. - */ - String[] notBeanPackages() default {}; - - /** - * Replace packages whose classes should not be considered beans. - * - * <p> - * Same as {@link #notBeanPackages()} but replaces any existing value. - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#notBeanPackages(String...)} - * </ul> - * - * @return The annotation value. - */ - String[] notBeanPackages_replace() default {}; - - /** - * Bean property namer. - * - * <p> - * The class to use for calculating bean property names. - * - * <p> - * Predefined classes: - * <ul> - * <li>{@link BasicPropertyNamer} (default) - * <li>{@link PropertyNamerDLC} - Dashed-lower-case names. - * <li>{@link PropertyNamerULC} - Dashed-upper-case names. - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#propertyNamer(Class)} - * </ul> - * - * @return The annotation value. - */ - Class<? extends PropertyNamer> propertyNamer() default PropertyNamer.Void.class; - /** * Optional rank for this config. * @@ -813,30 +182,6 @@ public @interface MarshalledConfig { */ int rank() default 0; - /** - * Disable sorted bean properties. - * - * <p> - * When <jk>true</jk>, bean properties are serialized and accessed in natural JVM order instead of the default alphabetical order. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default — properties are sorted alphabetically) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#unsortedProperties()} - * </ul> - * - * @return The annotation value. - */ - String unsortedProperties() default ""; - /** * Java object swaps. * @@ -922,53 +267,4 @@ public @interface MarshalledConfig { * @return The annotation value. */ String typePropertyName() default ""; - - /** - * Use enum names. - * - * <p> - * When enabled, enums are always serialized by name, not using {@link Object#toString()}. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#useEnumNames()} - * </ul> - * - * @return The annotation value. - */ - String useEnumNames() default ""; - - /** - * Use Java Introspector. - * - * <p> - * Using the built-in Java bean introspector will not pick up fields or non-standard getters/setters. - * <br>Most {@link Bean @Marshalled} annotations will be ignored. - * - * <ul class='values'> - * <li><js>"true"</js> - * <li><js>"false"</js> (default) - * </ul> - * - * <h5 class='section'>Notes:</h5><ul> - * <li class='note'> - * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). - * </ul> - * - * <h5 class='section'>See Also:</h5><ul> - * <li class='jm'>{@link org.apache.juneau.MarshallingContext.Builder#useJavaBeanIntrospector()} - * </ul> - * - * @return The annotation value. - */ - String useJavaBeanIntrospector() default ""; -} \ No newline at end of file +} diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledConfigAnnotation.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledConfigAnnotation.java index c5708159ce..9bc6c9d01a 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledConfigAnnotation.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/MarshalledConfigAnnotation.java @@ -17,12 +17,10 @@ package org.apache.juneau.annotation; import org.apache.juneau.commons.http.MediaType; -import static org.apache.juneau.commons.utils.CollectionUtils.*; import java.util.*; import org.apache.juneau.*; -import org.apache.juneau.commons.bean.*; import org.apache.juneau.commons.reflect.*; import org.apache.juneau.svl.*; @@ -56,28 +54,7 @@ public class MarshalledConfigAnnotation { MarshalledConfig a = ai.inner(); // @formatter:off - string(a.beanClassVisibility()).map(Visibility::valueOf).ifPresent(b::beanClassVisibility); - string(a.beanConstructorVisibility()).map(Visibility::valueOf).ifPresent(b::beanConstructorVisibility); - string(a.beanFieldVisibility()).map(Visibility::valueOf).ifPresent(b::beanFieldVisibility); - string(a.beanMethodVisibility()).map(Visibility::valueOf).ifPresent(b::beanMethodVisibility); - bool(a.beanMapPutReturnsOldValue()).ifPresent(b::beanMapPutReturnsOldValue); - bool(a.beansRequireDefaultConstructor()).ifPresent(b::beansRequireDefaultConstructor); - bool(a.beansRequireSerializable()).ifPresent(b::beansRequireSerializable); - bool(a.beansRequireSettersForGetters()).ifPresent(b::beansRequireSettersForGetters); - bool(a.disableBeansRequireSomeProperties()).ifPresent(b::disableBeansRequireSomeProperties); bool(a.debug()).ifPresent(b::debug); - bool(a.findFluentSetters()).ifPresent(b::findFluentSetters); - bool(a.ignoreInvocationExceptionsOnGetters()).ifPresent(b::ignoreInvocationExceptionsOnGetters); - bool(a.ignoreInvocationExceptionsOnSetters()).ifPresent(b::ignoreInvocationExceptionsOnSetters); - bool(a.disableIgnoreMissingSetters()).ifPresent(b::disableIgnoreMissingSetters); - bool(a.disableIgnoreTransientFields()).ifPresent(b::disableIgnoreTransientFields); - bool(a.ignoreUnknownBeanProperties()).ifPresent(b::ignoreUnknownBeanProperties); - bool(a.ignoreUnknownEnumValues()).ifPresent(b::ignoreUnknownEnumValues); - bool(a.disableIgnoreUnknownNullBeanProperties()).ifPresent(b::disableIgnoreUnknownNullBeanProperties); - bool(a.unsortedProperties()).ifPresent(b::unsortedProperties); - bool(a.useEnumNames()).ifPresent(b::useEnumNames); - bool(a.disableInterfaceProxies()).ifPresent(b::disableInterfaceProxies); - bool(a.useJavaBeanIntrospector()).ifPresent(b::useJavaBeanIntrospector); string(a.typePropertyName()).ifPresent(b::typePropertyName); string(a.locale()).map(Locale::forLanguageTag).ifPresent(b::locale); string(a.mediaType()).map(MediaType::of).ifPresent(b::mediaType); @@ -86,12 +63,6 @@ public class MarshalledConfigAnnotation { classes(a.dictionary_replace()).ifPresent(x -> { b.beanDictionary().clear(); b.beanDictionary(x);}); classes(a.swaps()).ifPresent(b::swaps); classes(a.swaps_replace()).ifPresent(x -> { b.swaps().clear(); b.swaps(x);}); - classes(a.notBeanClasses()).ifPresent(b::notBeanClasses); - classes(a.notBeanClasses_replace()).ifPresent(x -> { b.notBeanClasses().clear(); b.notBeanClasses(x);}); - type(a.propertyNamer()).ifPresent(b::propertyNamer); - l(a.interfaces()).stream().map(x -> BeanTypeApplyAnnotation.create(x).value(BeanTypeAnnotation.create().interfaceClass(x).build()).build()).forEach(b::annotations); - strings(a.notBeanPackages()).ifPresent(b::notBeanPackages); - strings(a.notBeanPackages_replace()).ifPresent(x -> {b.notBeanPackages().clear(); b.notBeanPackages(x);}); // @formatter:on } } diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/config/DefaultConfig.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/config/DefaultConfig.java index b5d4f64e7e..d4b1aa7172 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/config/DefaultConfig.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/config/DefaultConfig.java @@ -17,6 +17,7 @@ package org.apache.juneau.rest.config; import org.apache.juneau.annotation.*; +import org.apache.juneau.commons.bean.*; import org.apache.juneau.encoders.*; import org.apache.juneau.oapi.*; import org.apache.juneau.rest.annotation.*; @@ -126,7 +127,7 @@ import org.apache.juneau.serializer.annotation.*; staticFiles=StaticFiles.Void.class, // Defaults to BasicStaticFiles. swaggerProvider=SwaggerProvider.Void.class // Defaults to BasicSwaggerProvider. ) -@MarshalledConfig( +@BeanConfig( // When parsing generated beans, ignore unknown properties that may only exist as getters and not setters. ignoreUnknownBeanProperties="true", ignoreUnknownEnumValues="true" diff --git a/juneau-utest/src/test/java/org/apache/juneau/BasicBeans_Test.java b/juneau-utest/src/test/java/org/apache/juneau/BasicBeans_Test.java index ed14c2dc90..76b761b111 100644 --- a/juneau-utest/src/test/java/org/apache/juneau/BasicBeans_Test.java +++ b/juneau-utest/src/test/java/org/apache/juneau/BasicBeans_Test.java @@ -44,7 +44,7 @@ class BasicBeans_Test extends TestBase { } } - @MarshalledConfig(disableIgnoreTransientFields="true") + @BeanConfig(disableIgnoreTransientFields="true") public static class A {} @Test void a01_testTransientFieldsIgnored() { diff --git a/juneau-utest/src/test/java/org/apache/juneau/annotation/MarshalledConfigAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/annotation/BeanConfigAnnotation_Test.java similarity index 67% copy from juneau-utest/src/test/java/org/apache/juneau/annotation/MarshalledConfigAnnotation_Test.java copy to juneau-utest/src/test/java/org/apache/juneau/annotation/BeanConfigAnnotation_Test.java index 2aa142fe50..dba55f5826 100644 --- a/juneau-utest/src/test/java/org/apache/juneau/annotation/MarshalledConfigAnnotation_Test.java +++ b/juneau-utest/src/test/java/org/apache/juneau/annotation/BeanConfigAnnotation_Test.java @@ -30,23 +30,27 @@ import org.apache.juneau.commons.reflect.*; import org.apache.juneau.json.*; import org.apache.juneau.marshaller.*; import org.apache.juneau.svl.*; -import org.apache.juneau.swap.*; import org.junit.jupiter.api.*; import org.apache.juneau.commons.bean.*; /** - * Tests the @MarshalledConfig annotation. + * Tests the bean-modeling attributes of the @BeanConfig annotation. + * + * <p> + * These tests were extracted from {@code MarshalledConfigAnnotation_Test} during Phase 3 of the + * bean-layer split, when bean-modeling attributes moved off {@code @MarshalledConfig} onto + * {@code @BeanConfig} in {@code juneau-commons}. */ @SuppressWarnings({ "java:S5961" // High assertion count acceptable in comprehensive test }) -class MarshalledConfigAnnotation_Test extends TestBase { +class BeanConfigAnnotation_Test extends TestBase { private static void check(String expected, Object o) { assertEquals(expected, TO_STRING.apply(o)); } - private static final Function<Object,String> TO_STRING = new Function<>() { + private static final Function<Object,String> TO_STRING = new Function<>() { @Override public String apply(Object t) { if (t == null) @@ -108,18 +112,10 @@ class MarshalledConfigAnnotation_Test extends TestBase { public static class A3 { public int foo; } - public static class AB1 extends ObjectSwap<String,Integer> { - } - public static class AB2 extends ObjectSwap<String,Integer> { - } - public static class AB3 extends ObjectSwap<String,Integer> { - } - @MarshalledConfig( + @BeanConfig( beanClassVisibility="$X{PRIVATE}", beanConstructorVisibility="$X{PRIVATE}", - dictionary={A1.class,A2.class}, - dictionary_replace={A1.class,A2.class,A3.class}, beanFieldVisibility="$X{PRIVATE}", beanMapPutReturnsOldValue="$X{true}", beanMethodVisibility="$X{PRIVATE}", @@ -127,8 +123,6 @@ class MarshalledConfigAnnotation_Test extends TestBase { beansRequireSerializable="$X{true}", beansRequireSettersForGetters="$X{true}", disableBeansRequireSomeProperties="$X{true}", - typePropertyName="$X{foo}", - debug="$X{true}", disableIgnoreUnknownNullBeanProperties="$X{true}", disableIgnoreMissingSetters="$X{true}", disableInterfaceProxies="$X{true}", @@ -136,17 +130,12 @@ class MarshalledConfigAnnotation_Test extends TestBase { ignoreInvocationExceptionsOnGetters="$X{true}", ignoreInvocationExceptionsOnSetters="$X{true}", ignoreUnknownBeanProperties="$X{true}", - locale="$X{en-US}", - mediaType="$X{text/foo}", notBeanClasses={A1.class,A2.class}, notBeanClasses_replace={A1.class,A2.class,A3.class}, notBeanPackages={"$X{foo1}","$X{foo2}"}, notBeanPackages_replace={"$X{foo1}","$X{foo2}","$X{foo3}"}, - swaps={AB1.class,AB2.class}, - swaps_replace={AB1.class,AB2.class,AB3.class}, propertyNamer=PropertyNamerULC.class, unsortedProperties="$X{false}", - timeZone="$X{z}", useEnumNames="$X{true}", useJavaBeanIntrospector="$X{true}" ) @@ -159,7 +148,6 @@ class MarshalledConfigAnnotation_Test extends TestBase { check("PRIVATE", bs.getBeanClassVisibility()); check("PRIVATE", bs.getBeanConstructorVisibility()); - check("A1,A2,A3", bs.getBeanDictionary()); check("PRIVATE", bs.getBeanFieldVisibility()); check("true", bs.isBeanMapPutReturnsOldValue()); check("PRIVATE", bs.getBeanMethodVisibility()); @@ -167,22 +155,16 @@ class MarshalledConfigAnnotation_Test extends TestBase { check("true", bs.isBeansRequireSerializable()); check("true", bs.isBeansRequireSettersForGetters()); check("false", bs.isBeansRequireSomeProperties()); - check("foo", bs.getBeanTypePropertyName()); - check("true", bs.isDebug()); check("true", bs.isFindFluentSetters()); check("true", bs.isIgnoreInvocationExceptionsOnGetters()); check("true", bs.isIgnoreInvocationExceptionsOnSetters()); check("false", bs.isIgnoreMissingSetters()); check("true", bs.isIgnoreUnknownBeanProperties()); check("false", bs.isIgnoreUnknownNullBeanProperties()); - check("en_US", bs.getLocale()); - check("text/foo", bs.getMediaType()); check("A1,A2,A3,Map,Collection,Reader,Writer,InputStream,OutputStream,Throwable", bs.getNotBeanClasses()); check("foo1,foo2,foo3,java.lang,java.lang.annotation,java.lang.ref,java.lang.reflect,java.io,java.net", bs.getNotBeanPackagesNames()); - check("AB1<String,Integer>,AB2<String,Integer>,AB3<String,Integer>", bs.getSwaps()); check("PropertyNamerULC", bs.getPropertyNamer()); check("false", bs.isUnsortedProperties()); - check("GMT", bs.getTimeZone()); check("true", bs.isUseEnumNames()); check("false", bs.isUseInterfaceProxies()); check("true", bs.isUseJavaBeanIntrospector()); @@ -192,7 +174,7 @@ class MarshalledConfigAnnotation_Test extends TestBase { // Annotation with no values. //----------------------------------------------------------------------------------------------------------------- - @MarshalledConfig() + @BeanConfig() static class B {} static ClassInfo b = ClassInfo.of(B.class); @@ -202,52 +184,6 @@ class MarshalledConfigAnnotation_Test extends TestBase { var bc = js.getMarshallingContext(); check("PUBLIC", bc.getBeanClassVisibility()); check("PUBLIC", bc.getBeanConstructorVisibility()); - check("", bc.getBeanDictionary()); - check("PUBLIC", bc.getBeanFieldVisibility()); - check("false", bc.isBeanMapPutReturnsOldValue()); - check("PUBLIC", bc.getBeanMethodVisibility()); - check("false", bc.isBeansRequireDefaultConstructor()); - check("false", bc.isBeansRequireSerializable()); - check("false", bc.isBeansRequireSettersForGetters()); - check("true", bc.isBeansRequireSomeProperties()); - check("_type", bc.getBeanTypePropertyName()); - check("false", js.isDebug()); - check("false", js.isDetectRecursions()); - check("false", bc.isFindFluentSetters()); - check("false", bc.isIgnoreInvocationExceptionsOnGetters()); - check("false", bc.isIgnoreInvocationExceptionsOnSetters()); - check("true", bc.isIgnoreMissingSetters()); - check("false", js.isIgnoreRecursions()); - check("false", bc.isIgnoreUnknownBeanProperties()); - check("true", bc.isIgnoreUnknownNullBeanProperties()); - check("0", js.getInitialDepth()); - check(Locale.getDefault().toString(), bc.getDefaultLocale()); - check("100", js.getMaxDepth()); - check(null, bc.getDefaultMediaType()); - check("java.lang,java.lang.annotation,java.lang.ref,java.lang.reflect,java.io,java.net", bc.getNotBeanPackagesNames()); - check("", bc.getSwaps()); - check("BasicPropertyNamer", bc.getPropertyNamer()); - check("false", bc.isUnsortedProperties()); - check(null, bc.getDefaultTimeZone()); - check("false", bc.isUseEnumNames()); - check("true", bc.isUseInterfaceProxies()); - check("false", bc.isUseJavaBeanIntrospector()); - } - - //----------------------------------------------------------------------------------------------------------------- - // No annotation. - //----------------------------------------------------------------------------------------------------------------- - - static class C {} - static ClassInfo c = ClassInfo.of(C.class); - - @Test void c01_noAnnotation() { - var al = AnnotationWorkList.of(sr, rstream(c.getAnnotations())); - var js = JsonSerializer.create().apply(al).build(); - var bc = js.getMarshallingContext(); - check("PUBLIC", bc.getBeanClassVisibility()); - check("PUBLIC", bc.getBeanConstructorVisibility()); - check("", bc.getBeanDictionary()); check("PUBLIC", bc.getBeanFieldVisibility()); check("false", bc.isBeanMapPutReturnsOldValue()); check("PUBLIC", bc.getBeanMethodVisibility()); @@ -255,27 +191,17 @@ class MarshalledConfigAnnotation_Test extends TestBase { check("false", bc.isBeansRequireSerializable()); check("false", bc.isBeansRequireSettersForGetters()); check("true", bc.isBeansRequireSomeProperties()); - check("_type", bc.getBeanTypePropertyName()); - check("false", js.isDebug()); - check("false", js.isDetectRecursions()); check("false", bc.isFindFluentSetters()); check("false", bc.isIgnoreInvocationExceptionsOnGetters()); check("false", bc.isIgnoreInvocationExceptionsOnSetters()); check("true", bc.isIgnoreMissingSetters()); - check("false", js.isIgnoreRecursions()); check("false", bc.isIgnoreUnknownBeanProperties()); check("true", bc.isIgnoreUnknownNullBeanProperties()); - check("0", js.getInitialDepth()); - check(Locale.getDefault().toString(), bc.getDefaultLocale()); - check("100", js.getMaxDepth()); - check(null, bc.getDefaultMediaType()); check("java.lang,java.lang.annotation,java.lang.ref,java.lang.reflect,java.io,java.net", bc.getNotBeanPackagesNames()); - check("", bc.getSwaps()); check("BasicPropertyNamer", bc.getPropertyNamer()); check("false", bc.isUnsortedProperties()); - check(null, bc.getDefaultTimeZone()); check("false", bc.isUseEnumNames()); check("true", bc.isUseInterfaceProxies()); check("false", bc.isUseJavaBeanIntrospector()); } -} \ No newline at end of file +} diff --git a/juneau-utest/src/test/java/org/apache/juneau/annotation/MarshalledConfigAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/annotation/MarshalledConfigAnnotation_Test.java index 2aa142fe50..c0d6b2a06e 100644 --- a/juneau-utest/src/test/java/org/apache/juneau/annotation/MarshalledConfigAnnotation_Test.java +++ b/juneau-utest/src/test/java/org/apache/juneau/annotation/MarshalledConfigAnnotation_Test.java @@ -35,7 +35,11 @@ import org.junit.jupiter.api.*; import org.apache.juneau.commons.bean.*; /** - * Tests the @MarshalledConfig annotation. + * Tests the marshalling-only attributes of the @MarshalledConfig annotation. + * + * <p> + * The bean-modeling attributes were moved to {@code @BeanConfig} in Phase 3 of the bean-layer split. + * See {@code BeanConfigAnnotation_Test} for tests on those attributes. */ @SuppressWarnings({ "java:S5961" // High assertion count acceptable in comprehensive test @@ -116,39 +120,15 @@ class MarshalledConfigAnnotation_Test extends TestBase { } @MarshalledConfig( - beanClassVisibility="$X{PRIVATE}", - beanConstructorVisibility="$X{PRIVATE}", dictionary={A1.class,A2.class}, dictionary_replace={A1.class,A2.class,A3.class}, - beanFieldVisibility="$X{PRIVATE}", - beanMapPutReturnsOldValue="$X{true}", - beanMethodVisibility="$X{PRIVATE}", - beansRequireDefaultConstructor="$X{true}", - beansRequireSerializable="$X{true}", - beansRequireSettersForGetters="$X{true}", - disableBeansRequireSomeProperties="$X{true}", typePropertyName="$X{foo}", debug="$X{true}", - disableIgnoreUnknownNullBeanProperties="$X{true}", - disableIgnoreMissingSetters="$X{true}", - disableInterfaceProxies="$X{true}", - findFluentSetters="$X{true}", - ignoreInvocationExceptionsOnGetters="$X{true}", - ignoreInvocationExceptionsOnSetters="$X{true}", - ignoreUnknownBeanProperties="$X{true}", locale="$X{en-US}", mediaType="$X{text/foo}", - notBeanClasses={A1.class,A2.class}, - notBeanClasses_replace={A1.class,A2.class,A3.class}, - notBeanPackages={"$X{foo1}","$X{foo2}"}, - notBeanPackages_replace={"$X{foo1}","$X{foo2}","$X{foo3}"}, swaps={AB1.class,AB2.class}, swaps_replace={AB1.class,AB2.class,AB3.class}, - propertyNamer=PropertyNamerULC.class, - unsortedProperties="$X{false}", - timeZone="$X{z}", - useEnumNames="$X{true}", - useJavaBeanIntrospector="$X{true}" + timeZone="$X{z}" ) static class A {} static ClassInfo a = ClassInfo.of(A.class); @@ -157,35 +137,13 @@ class MarshalledConfigAnnotation_Test extends TestBase { var al = AnnotationWorkList.of(sr, rstream(a.getAnnotations())); var bs = JsonSerializer.create().apply(al).build().getSession(); - check("PRIVATE", bs.getBeanClassVisibility()); - check("PRIVATE", bs.getBeanConstructorVisibility()); check("A1,A2,A3", bs.getBeanDictionary()); - check("PRIVATE", bs.getBeanFieldVisibility()); - check("true", bs.isBeanMapPutReturnsOldValue()); - check("PRIVATE", bs.getBeanMethodVisibility()); - check("true", bs.isBeansRequireDefaultConstructor()); - check("true", bs.isBeansRequireSerializable()); - check("true", bs.isBeansRequireSettersForGetters()); - check("false", bs.isBeansRequireSomeProperties()); check("foo", bs.getBeanTypePropertyName()); check("true", bs.isDebug()); - check("true", bs.isFindFluentSetters()); - check("true", bs.isIgnoreInvocationExceptionsOnGetters()); - check("true", bs.isIgnoreInvocationExceptionsOnSetters()); - check("false", bs.isIgnoreMissingSetters()); - check("true", bs.isIgnoreUnknownBeanProperties()); - check("false", bs.isIgnoreUnknownNullBeanProperties()); check("en_US", bs.getLocale()); check("text/foo", bs.getMediaType()); - check("A1,A2,A3,Map,Collection,Reader,Writer,InputStream,OutputStream,Throwable", bs.getNotBeanClasses()); - check("foo1,foo2,foo3,java.lang,java.lang.annotation,java.lang.ref,java.lang.reflect,java.io,java.net", bs.getNotBeanPackagesNames()); check("AB1<String,Integer>,AB2<String,Integer>,AB3<String,Integer>", bs.getSwaps()); - check("PropertyNamerULC", bs.getPropertyNamer()); - check("false", bs.isUnsortedProperties()); check("GMT", bs.getTimeZone()); - check("true", bs.isUseEnumNames()); - check("false", bs.isUseInterfaceProxies()); - check("true", bs.isUseJavaBeanIntrospector()); } //----------------------------------------------------------------------------------------------------------------- @@ -200,38 +158,17 @@ class MarshalledConfigAnnotation_Test extends TestBase { var al = AnnotationWorkList.of(sr, rstream(b.getAnnotations())); var js = JsonSerializer.create().apply(al).build(); var bc = js.getMarshallingContext(); - check("PUBLIC", bc.getBeanClassVisibility()); - check("PUBLIC", bc.getBeanConstructorVisibility()); check("", bc.getBeanDictionary()); - check("PUBLIC", bc.getBeanFieldVisibility()); - check("false", bc.isBeanMapPutReturnsOldValue()); - check("PUBLIC", bc.getBeanMethodVisibility()); - check("false", bc.isBeansRequireDefaultConstructor()); - check("false", bc.isBeansRequireSerializable()); - check("false", bc.isBeansRequireSettersForGetters()); - check("true", bc.isBeansRequireSomeProperties()); check("_type", bc.getBeanTypePropertyName()); check("false", js.isDebug()); check("false", js.isDetectRecursions()); - check("false", bc.isFindFluentSetters()); - check("false", bc.isIgnoreInvocationExceptionsOnGetters()); - check("false", bc.isIgnoreInvocationExceptionsOnSetters()); - check("true", bc.isIgnoreMissingSetters()); check("false", js.isIgnoreRecursions()); - check("false", bc.isIgnoreUnknownBeanProperties()); - check("true", bc.isIgnoreUnknownNullBeanProperties()); check("0", js.getInitialDepth()); check(Locale.getDefault().toString(), bc.getDefaultLocale()); check("100", js.getMaxDepth()); check(null, bc.getDefaultMediaType()); - check("java.lang,java.lang.annotation,java.lang.ref,java.lang.reflect,java.io,java.net", bc.getNotBeanPackagesNames()); check("", bc.getSwaps()); - check("BasicPropertyNamer", bc.getPropertyNamer()); - check("false", bc.isUnsortedProperties()); check(null, bc.getDefaultTimeZone()); - check("false", bc.isUseEnumNames()); - check("true", bc.isUseInterfaceProxies()); - check("false", bc.isUseJavaBeanIntrospector()); } //----------------------------------------------------------------------------------------------------------------- @@ -245,37 +182,16 @@ class MarshalledConfigAnnotation_Test extends TestBase { var al = AnnotationWorkList.of(sr, rstream(c.getAnnotations())); var js = JsonSerializer.create().apply(al).build(); var bc = js.getMarshallingContext(); - check("PUBLIC", bc.getBeanClassVisibility()); - check("PUBLIC", bc.getBeanConstructorVisibility()); check("", bc.getBeanDictionary()); - check("PUBLIC", bc.getBeanFieldVisibility()); - check("false", bc.isBeanMapPutReturnsOldValue()); - check("PUBLIC", bc.getBeanMethodVisibility()); - check("false", bc.isBeansRequireDefaultConstructor()); - check("false", bc.isBeansRequireSerializable()); - check("false", bc.isBeansRequireSettersForGetters()); - check("true", bc.isBeansRequireSomeProperties()); check("_type", bc.getBeanTypePropertyName()); check("false", js.isDebug()); check("false", js.isDetectRecursions()); - check("false", bc.isFindFluentSetters()); - check("false", bc.isIgnoreInvocationExceptionsOnGetters()); - check("false", bc.isIgnoreInvocationExceptionsOnSetters()); - check("true", bc.isIgnoreMissingSetters()); check("false", js.isIgnoreRecursions()); - check("false", bc.isIgnoreUnknownBeanProperties()); - check("true", bc.isIgnoreUnknownNullBeanProperties()); check("0", js.getInitialDepth()); check(Locale.getDefault().toString(), bc.getDefaultLocale()); check("100", js.getMaxDepth()); check(null, bc.getDefaultMediaType()); - check("java.lang,java.lang.annotation,java.lang.ref,java.lang.reflect,java.io,java.net", bc.getNotBeanPackagesNames()); check("", bc.getSwaps()); - check("BasicPropertyNamer", bc.getPropertyNamer()); - check("false", bc.isUnsortedProperties()); check(null, bc.getDefaultTimeZone()); - check("false", bc.isUseEnumNames()); - check("true", bc.isUseInterfaceProxies()); - check("false", bc.isUseJavaBeanIntrospector()); } -} \ No newline at end of file +}
