Class BeanMeta<T>

java.lang.Object
org.apache.juneau.commons.bean.BeanMeta<T>
Type Parameters:
T - The class type that this metadata applies to.

public class BeanMeta<T> extends Object
Encapsulates all access to the properties of a bean class (like a souped-up BeanInfo).
Description
Uses introspection to find all the properties associated with this class. If the @BeanType annotation is present on the class (or the marshalling-side @Marshalled sibling), that information is used to determine the properties on the class. Otherwise, the BeanInfo functionality in Java is used to determine the properties on the class.
Bean property ordering
The order of the properties is as follows:
  • If @BeanType(properties) is specified on the class, the order matches the list of properties in the annotation.
  • Otherwise, by default, properties are sorted alphabetically.
  • When unsorted properties are enabled (BeanConfigContext.isUnsortedProperties(), @BeanType(unsorted=true), or a bean filter), properties use declaration order:
    • Records: record component order.
    • Other classes: field declaration order, superclass fields first. Getter/setter properties are ranked by their same-named field (even a private one), which is used as an ordering hint only.
    • Method-only properties (no backing field) follow, alphabetically.
  • BeanConfigContext.isRecordComponentOrder() gives records component order even when other beans are sorted.

Field order comes from Class.getDeclaredFields(), which is declaration order on HotSpot and OpenJ9 but is not guaranteed by the JLS.

Thread safety
Instances are effectively immutable after construction and are safe for concurrent read access. Construction is not thread-safe and should be completed before sharing an instance across threads.
  • Constructor Details

    • BeanMeta

      protected BeanMeta(BeanInfo<T> cm, BeanFilter bf, String[] pNames, ClassInfo implClass)
      Constructor.

      Creates a new BeanMeta instance for the specified class metadata. This constructor performs introspection to discover all bean properties, methods, and fields in the class hierarchy.

      The bean metadata is built by:

      • Finding all bean fields in the class hierarchy
      • Finding all bean methods (getters, setters, extraKeys) in the class hierarchy
      • Determining the appropriate constructor for bean instantiation
      • Building the class hierarchy for property discovery
      • Creating the bean registry for dictionary name resolution
      • Validating and filtering properties based on bean filter settings
      Parameters:
      cm - The class metadata for the bean class. Must not be null.
      bf - Optional bean filter to apply. Can be null (no bean filter customizations are applied; the default stop class of Object is used).
      pNames - Explicit list of property names and order. If null, properties are determined automatically.
      implClass - Optional implementation class constructor to use if one cannot be found. Can be null (the bean class's own no-arg constructor is used instead).
    • BeanMeta

      protected BeanMeta(BeanInfo<T> cm, BeanFilter bf, String[] pNames, ClassInfo implClass, PropertyNamer propertyNamerOverride)
      Parameters:
      cm - The class metadata for the bean class. Must not be null.
      bf - Optional bean filter to apply. Can be null (no bean filter customizations are applied; the default stop class of Object is used).
      pNames - Explicit list of property names and order. If null, properties are determined automatically.
      implClass - Optional implementation class constructor to use if one cannot be found. Can be null (the bean class's own no-arg constructor is used instead).
      propertyNamerOverride - Optional namer that, when non-null, takes precedence over the bean filter and BeanConfigContext.getPropertyNamer() for deriving property names.
    • BeanMeta

      protected BeanMeta(Class<T> beanClass, BeanConfigContext config)
      Bean-modeling constructor — builds a BeanMeta without marshalling context state.

      See of(Class, BeanConfigContext) for the public entry point. The getBeanInfo(), bean type resolver, and per-property registry lookups are left null; the per-property rawTypeMeta/typeMeta fields are also null (no type-resolution is performed in this path).

      Parameters:
      beanClass - The bean class. Must not be null.
      config - The bean-modeling configuration. Must not be null.
  • Method Details

    • create

      public static <T> BeanMeta.BeanMetaValue<T> create(BeanInfo<T> cm, ClassInfo implClass)
      Creates a BeanMeta instance for the specified bean type info.

      This is the marshalling-side factory entry point. It attempts to create bean metadata for a class; if the class is determined to be a bean, the returned BeanMeta.BeanMetaValue carries the BeanMeta instance and a null reason. Otherwise it carries null for the bean metadata and a non-empty string explaining why the class is not a bean.

      The bean filter is resolved internally from the @Marshalled / @BeanType annotations on the class via BeanMetaInitializer.buildBeanFilter(BeanInfo). See of(Class, BeanConfigContext) for the pure bean-modeling-side entry point that does not require a BeanInfo.

      Exception handling:

      If a RuntimeException is thrown during bean metadata creation, it is caught and the exception message is returned as the notABeanReason with null for the bean metadata.

      Example:

      // Create bean metadata for a class via the marshalling-side context. BeanInfo<Person> cm = marshallingContext.getClassMeta(Person.class); BeanMetaHolder<Person> result = BeanMeta.create(cm, null); // Check if it's a bean if (result.beanMeta() != null) { BeanMeta<Person> bm = result.beanMeta(); // Use the bean metadata... } else { String reason = result.notABeanReason(); // Handle the case where it's not a bean... }

      Type Parameters:
      T - The class type.
      Parameters:
      cm - The bean type info for the class to create bean metadata for. Must not be null.
      implClass - Optional implementation class info to use when looking for a no-arg constructor. Can be null (the bean class's own no-arg constructor is used instead).
      Returns:
      A BeanMeta.BeanMetaValue containing the bean metadata (if successful) or a reason why it's not a bean.
    • create

      public static <T> BeanMeta.BeanMetaValue<T> create(BeanInfo<T> cm, ClassInfo implClass, PropertyNamer propertyNamer)
      Same as create(BeanInfo, ClassInfo) but allows an explicit PropertyNamer to override the one that would otherwise be derived from the bean filter or BeanConfigContext.getPropertyNamer().

      The returned BeanMeta is not cached anywhere — callers that need a namer-specific view (for example, MarshallingSession#toBeanMap(Object, PropertyNamer)) build one on demand so the shared, Class-keyed default BeanMeta cache is never polluted with alternate-namer property keys.

      Type Parameters:
      T - The class type.
      Parameters:
      cm - The bean type info for the class to create bean metadata for. Must not be null.
      implClass - Optional implementation class info to use when looking for a no-arg constructor. Can be null (the bean class's own no-arg constructor is used instead).
      propertyNamer - Optional property namer to use for deriving property names. If null, the namer is resolved the normal way (bean filter, then BeanConfigContext.getPropertyNamer()).
      Returns:
      A BeanMeta.BeanMetaValue containing the bean metadata (if successful) or a reason why it's not a bean.
    • of

      public static <T> BeanMeta<T> of(Class<T> beanClass, BeanConfigContext config)
      Creates a BeanMeta for the specified class using the supplied BeanConfigContext.

      This is the bean-modeling entry point — it constructs a BeanMeta purely from a Class and a BeanConfigContext, without touching any marshalling-side type infrastructure. The returned BeanMeta carries enough information to do raw getter/setter invocation and property iteration; marshalling-aware reads (getBeanInfo(), type-resolution on each BeanPropertyMeta.getBeanInfo(), the per-property registry lookup) remain null.

      Example:

      BeanMeta<Person> bm = BeanMeta.of(Person.class, BeanConfigContext.DEFAULT); BeanPropertyMeta name = bm.getProperties().get("name");

      Type Parameters:
      T - The bean class type.
      Parameters:
      beanClass - The class to build a BeanMeta for. Must not be null.
      config - The bean-modeling configuration to apply. Must not be null.
      Returns:
      A new BeanMeta for the specified class.
    • of

      public static <T> BeanMeta<T> of(Class<T> beanClass)
      Type Parameters:
      T - The bean class type.
      Parameters:
      beanClass - The class to build a BeanMeta for. Must not be null.
      Returns:
      A new BeanMeta for the specified class.
    • equals

      public boolean equals(Object o)
      Overrides:
      equals in class Object
    • getBeanFilter

      Returns the bean filter associated with this bean.

      Bean filters are used to control aspects of how beans are handled during serialization and parsing, such as property inclusion/exclusion, property ordering, and type name mapping.

      On the marshalling-side construction path, the bean filter is typically built from the @Marshalled and @BeanType annotations on the class. If neither annotation is present (or this BeanMeta was built via the commons-side path), this method returns null.

      Returns:
      The bean filter for this bean, or null if no bean filter is associated with this bean.
    • getBeanProxyInvocationHandler

      Returns the proxy invocation handler for this bean if it's an interface.
      Returns:
      The invocation handler, or null if this is not an interface or interface proxies are disabled.
    • getBeanRegistry

      Returns the bean registry for this bean.

      The bean registry is used to resolve dictionary names to class types. It's created when a bean class has a @Marshalled(dictionary) annotation that specifies a list of possible subclasses.

      Returns the bean-modeling-side SPI type (BeanRegistryLookup).

      Returns:
      The bean registry for this bean, or null if no bean registry is associated with it.
    • getPropertyBeanRegistry

      Returns the per-property registry lookup associated with the given BeanPropertyMeta.

      BeanPropertyMeta no longer carries a concrete registry field — the per-property registry now lives in a side-map on this BeanMeta keyed by the property meta itself. The serializer and parser sides still need to look up the property-level registry for polymorphic dispatch; they now route through this accessor (directly or via the deprecated-style BeanPropertyMeta.getBeanRegistry() delegate).

      The returned registry chains the property's @MarshalledProp(dictionary) entries on top of the bean-level registry, which in turn chains on top of the global bean dictionary.

      Parameters:
      p - The bean property meta to look up. Can be a normal property, the synthetic "_type" property, or any other property meta produced by this bean.
      Returns:
      The bean registry for the specified property, or null if none was registered (e.g. the property belongs to a different bean meta).
    • getBeanInfo

      public BeanInfo<T> getBeanInfo()
      Returns the BeanInfo of this bean.

      Returns null when this BeanMeta was constructed via the commons-side path (of(Class, BeanConfigContext)) — in that case getClassInfo() carries the pure-reflection view of the bean class.

      Returns the bean-modeling-side SPI type (BeanInfo).

      Returns:
      The BeanInfo of this bean, or null for bean-modeling-only construction.
    • getClassInfo

      Returns the ClassInfo of this bean.

      Pure-reflection view of the bean class. Always non-null, regardless of construction path. Use this in preference to getBeanInfo() for any bean-modeling read that does not depend on marshalling-aware type metadata; the commons-side construction path leaves getBeanInfo() null.

      Returns:
      The class info for this bean. Never null.
    • getConfig

      Returns the bean-modeling configuration snapshot used to build this BeanMeta.

      For marshalling-side construction, this is sourced from the owning marshalling context. For commons-side construction (via of(Class, BeanConfigContext)), this is the BeanConfigContext passed to the factory. Always non-null.

      Returns:
      The bean-modeling configuration. Never null.
    • getDictionaryName

      Returns the dictionary name for this bean as defined through the @Marshalled(typeName) annotation.
      Returns:
      The dictionary name for this bean, or null if it has no dictionary name defined.
    • getProperties

      Returns a map of all properties on this bean.

      The map is keyed by property name and contains BeanPropertyMeta objects that provide metadata about each property, including its type, getter/setter methods, field information, and serialization/parsing behavior.

      This map contains only the normal (non-hidden) properties of the bean. Hidden properties can be accessed via getHiddenProperties().

      Returns:
      A map of property names to their metadata. The map is unmodifiable.
      See Also:
    • getPropertyMeta

      Returns metadata about the specified property.
      Parameters:
      name - The name of the property on this bean. Can be null to return the dynamic ("*") property.
      Returns:
      The metadata about the property, or null if no such property exists on this bean.
    • getTypeProperty

      Returns a mock bean property that resolves to the name "_type" and whose value always resolves to the dictionary name of the bean.
      Returns:
      The type name property.
    • getTypePropertyName

      Returns the type property name for this bean.

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

      If null, "_type" should be assumed.

      The value is determined from:

      Returns:
      The type property name associated with this bean, or null if the default "_type" should be used.
      See Also:
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class Object
    • onReadProperty

      public Object onReadProperty(Object bean, String name, Object value)
      Property read interceptor.

      Called immediately after calling the getter to allow the value to be overridden.

      Parameters:
      bean - The bean from which the property was read.
      name - The property name.
      value - The value just extracted from calling the bean getter.
      Returns:
      The value to serialize. Default is just to return the existing value.
    • onWriteProperty

      public Object onWriteProperty(Object bean, String name, Object value)
      Property write interceptor.

      Called immediately before calling theh setter to allow value to be overwridden.

      Parameters:
      bean - The bean from which the property was read.
      name - The property name.
      value - The value just parsed.
      Returns:
      The value to serialize. Default is just to return the existing value.
    • properties

    • toString

      public String toString()
      Overrides:
      toString in class Object
    • getBeanTypeResolver

      Returns the bean-modeling BeanTypeResolver that this metadata was constructed against.

      On the marshalling-side construction path, the underlying object is the marshalling context (which implements BeanTypeResolver); marshalling-side callers that need the concrete narrowing must cast (e.g. (MarshallingContext) bm.getBeanTypeResolver()).

      Returns null when this BeanMeta was constructed via the commons-side path (of(Class, BeanConfigContext)). Use getConfig() for the always-non-null bean-modeling configuration facade.

      Returns:
      The bean-modeling type resolver, or null for bean-modeling-only construction.
    • getConstructor

      Returns the constructor for this bean, if one was found.

      The constructor is determined by findBeanConstructor() and may be:

      • A constructor annotated with @BeanCtor
      • An implementation class constructor (if provided)
      • A no-argument constructor
      • null if no suitable constructor was found
      Returns:
      The constructor for this bean, or null if no constructor is available.
      See Also:
    • getConstructorArgs

      Returns the list of property names that correspond to the constructor parameters.

      The property names are in the same order as the constructor parameters. These names are used to map parsed property values to constructor arguments when creating bean instances.

      The property names are determined from:

      • The properties() value in the @BeanCtor annotation (if present)
      • Otherwise, the parameter names from the constructor (if available in bytecode)

      If the bean has no constructor or uses a no-argument constructor, this list will be empty.

      Returns:
      A list of property names corresponding to constructor parameters, in parameter order.
      See Also:
    • getDynaProperty

      Returns the "extras" property for dynamic bean properties.
      Returns:
      The dynamic property, or null if not present.
    • getGetterProps

      Returns the map of getter methods to property names.
      Returns:
      The getter properties map.
    • getHiddenProperties

      Returns the map of hidden properties on this bean.

      Hidden properties are properties that exist on the bean but are not included in the normal property list. These properties are typically excluded from serialization but may still be accessible programmatically.

      Hidden properties can be defined through:

      Returns:
      A map of hidden property names to their metadata. The map is unmodifiable.
      See Also:
    • getSetterProps

      Returns the map of setter methods to property names.
      Returns:
      The setter properties map.
    • hasConstructor

      public boolean hasConstructor()
      Returns whether this bean has a constructor available for instantiation.

      A bean has a constructor if findBeanConstructor() was able to find a suitable constructor, which may be:

      • A constructor annotated with @BeanCtor
      • An implementation class constructor (if provided)
      • A no-argument constructor

      If this method returns false, the bean cannot be instantiated using newBean(Object), and may need to be created through other means (e.g., interface proxies).

      Returns:
      true if a constructor is available, false otherwise.
      See Also:
    • hasRequiredProperties

      public boolean hasRequiredProperties()
      Returns whether any property of this bean is marked @BeanProp(required=true).
      Returns:
      true if at least one property is required.
    • getRequiredPropertyNames

      Returns the names of the properties marked @BeanProp(required=true).

      Hidden and excluded properties are not included, since input can never set them.

      Example:

      public record Person(@BeanProp(required=true) String name, Integer age) {} // [name] List<String> required = BeanMeta.of(Person.class, BeanConfigContext.DEFAULT).getRequiredPropertyNames();

      Returns:
      An unmodifiable list of property names, in property order. Never null.
    • isUnsortedProperties

      protected boolean isUnsortedProperties()
      Returns whether this bean has opted out of alphabetical property sorting.
      Returns:
      true if properties use declaration order (see the class Javadoc).
    • newBean

      public T newBean(Object outer) throws ExecutableException
      Creates a new instance of this bean.
      Parameters:
      outer - The outer object if bean class is a non-static inner member class. Can be null if not applicable.
      Returns:
      A new instance of this bean if possible, or null if not.
      Throws:
      ExecutableException - Exception occurred on invoked constructor/method/field.