Annotation Interface BeanProp


Annotation that can be applied to bean fields, getter/setter methods, and constructor parameters to control bean introspection and property modeling.

The bean-modeling sibling of @MarshalledProp. Where @MarshalledProp (in juneau-marshall) carries the marshalling-only attributes (such as dictionary, format, and properties), this annotation carries the attributes that describe the bean property itself — its name, accessibility (read/write only), concrete type, generic type parameters, element type, and the bean factory used to instantiate its value.

Splitting the annotations lets a property participate in the bean model (for example, to declare its name or read-only semantics) without dragging in any marshalling concerns, and lets the bean-modeling layer live in juneau-commons independent of juneau-marshall.

Can be used in the following locations:

  • Bean fields, getter methods, and setter methods.
  • Constructor parameters.
See Also:
  • Optional Element Summary

    Optional Elements
    Modifier and Type
    Optional Element
    Description
    Optional description for the exposed API.
    Element type for streaming/consuming bean properties.
    Class<? extends BeanFactory>
    Bean factory class for this property's value.
    Identifies the name of the property.
    Class<?>[]
    For bean properties of maps and collections, this annotation can be used to identify the class types of the contents of the bean property object when the generic parameter types are interfaces or abstract classes.
    boolean
    Marks this property as required on input.
    Identifies a property as read-only.
    Short, concise summary of the exposed API.
    Identifies a specialized class type for the property.
    A synonym for name().
    Identifies a property as write-only.
  • Element Details

    • description

      Optional description for the exposed API.
      Returns:
      The annotation value.
      Since:
      9.2.0
      Default:
      {}
    • summary

      Short, concise summary of the exposed API.

      Intended as a brief, single-line description suitable for AI/LLM consumption, compact documentation, or any context where brevity matters. See Schema.summary() for the canonical definition; this field is the bean-property-level counterpart.

      Returns:
      The annotation value.
      Since:
      10.0.0
      Default:
      ""
    • elementType

      Element type for streaming/consuming bean properties.

      Specifies the element type for properties of type Stream, BeanSupplier, BeanConsumer, or BeanChannel when type erasure prevents the framework from inferring the generic type argument at runtime.

      This attribute also supports:

      • Narrowing - Specify a more specific subtype than the declared type
      • Concrete implementation - Specify a concrete class for an abstract/interface element type
      Example:

      public class OrderCollection { // Stream property - element type cannot be inferred at runtime due to erasure @BeanProp(elementType=Order.class) public Stream<Order> getOrders() { ... } // BeanChannel with concrete impl specified instead of abstract element type @BeanProp(elementType=ConcreteItem.class) public BeanChannel<AbstractItem> getItems() { ... } }

      See Also:
      Returns:
      The annotation value.
      Default:
      void.class
    • factory

      Bean factory class for this property's value.

      Specifies a BeanFactory class to use when instantiating the value of this specific bean property, overriding the class-level BeanType.factory() if present.

      When a factory class is specified, the framework resolves it in the following order:

      1. Look up the factory class in the configured BeanStore
      2. Attempt direct instantiation via no-arg constructor or getInstance() static method
      3. Throw IllegalArgumentException if both fail
      Example:

      public class MyBean { @BeanProp(factory=ItemChannelFactory.class, elementType=Item.class) public BeanChannel<Item> getItems() { ... } }

      See Also:
      Returns:
      The annotation value.
      Default:
      org.apache.juneau.commons.function.BeanFactory.Void.class
    • name

      Identifies the name of the property.

      Normally, this is automatically inferred from the field name or getter method name of the property. However, this property can be used to assign a different property name from the automatically inferred value.

      Dynamic beans

      On a field whose type is not a Map, "*" does not create a dynamic property: the property name is the field name (same as omitting name/value), while other attributes on this annotation still apply.

      The bean property named "*" is the designated "dynamic property" which allows for "extra" bean properties not otherwise defined.

      The following examples show how to define dynamic bean properties.

      // Option #1 - A simple public Map field. // The field name can be anything. public class BeanWithDynaField { @BeanProp(name="*") public Map<String,Object> extraStuff = new LinkedHashMap<>(); } // Option #2 - Getters and setters. // Method names can be anything. // Getter must return a Map with String keys. // Setter must take in two arguments. public class BeanWithDynaMethods { @BeanProp(name="*") public Map<String,Object> getMyExtraStuff() { ... } @BeanProp(name="*") public void setAnExtraField(String name, Object value) { ... } }

      Note that the @Name annotation can also be used for identifying a property name.
      Returns:
      The annotation value.
      Default:
      ""
    • params

      For bean properties of maps and collections, this annotation can be used to identify the class types of the contents of the bean property object when the generic parameter types are interfaces or abstract classes.
      Example:

      public class MyBean { // Identify concrete map type with String keys and Integer values. @BeanProp(type=HashMap.class, params={String.class,Integer.class}) public Map p1; }

      Returns:
      The annotation value.
      Default:
      {}
    • required

      boolean required
      Marks this property as required on input.

      When true, parsers (and Map-to-bean conversion) throw a org.apache.juneau.marshall.parser.MissingRequiredPropertyException if the input does not contain this property. The check runs once per bean, before the bean is constructed, so records and constructor-argument beans get a clear error instead of a constructor failure.

      "Present" means the key appears in the input. An explicit null value counts as present; use your own validation (or a compact record constructor) to reject null values.

      The flag is OR-merged across the field, getter and setter: annotating any one of them makes the property required. Wrapping an existing object (for example MarshallingSession.toBeanMap(Object)) never checks.

      This attribute is independent of @Schema(required), which only affects generated schema documentation and HTTP part validation.

      Example:

      public record Person(@BeanProp(required=true) String name, Integer age) {} // Throws MissingRequiredPropertyException: // Missing required properties on bean class 'Person': [name] JsonParser.DEFAULT.read("{\"age\":30}", Person.class); // OK: explicit null counts as present. JsonParser.DEFAULT.read("{\"name\":null}", Person.class);

      Notes:
      • A required property must be writable (a field, setter or constructor argument). Marking a read-only property required fails when the bean metadata is built.
      • For builder-based beans, put the annotation on the builder's setter.
      • On a non-record bean, put the annotation on the field or getter; it is not read from constructor parameters.
      • In REST methods, a missing required property in an @Content body produces 400 Bad Request.
      Returns:
      true if this property must be present in the input.
      Default:
      false
    • ro

      Identifies a property as read-only.

      Serializers will serialize such properties as usual, but parsers will silently ignore them.

      Example:

      public class MyBean { @BeanProp(ro="true") public float price; }

      Notes:
      • Java Records: Marking record components as read-only is not supported during parsing. Because records are immutable, all components must be provided to the canonical constructor. Read-only components will be serialized as usual, but the parser will be unable to instantiate the record if the read-only component values are missing from the input.
      Returns:
      The annotation value.
      Default:
      ""
    • type

      Identifies a specialized class type for the property.

      Normally this can be inferred through reflection of the field type or getter return type. However, you'll want to specify this value if you're parsing beans where the bean property class is an interface or abstract class to identify the bean type to instantiate. Otherwise, you may cause an InstantiationException when trying to set these fields.

      This property must denote a concrete bean class with a no-arg constructor.

      Example:

      public class MyBean { // Identify concrete map type. @BeanProp(type=HashMap.class) public Map p1; }

      Returns:
      The annotation value.
      Default:
      void.class
    • value

      A synonym for name().

      The following annotations are equivalent:

      @BeanProp(name="foo") @BeanProp("foo")

      Returns:
      The annotation value.
      Default:
      ""
    • wo

      Identifies a property as write-only.

      Parsers will parse such properties as usual, but serializers will silently ignore them.

      Example:

      public class MyBean { @BeanProp(wo="true") public float price; }

      Returns:
      The annotation value.
      Default:
      ""