@BeanProp Annotation
The @BeanProp annotation is applied to bean fields, getter/setter methods, and constructor parameters to control bean introspection and property modeling.
This is the model-side annotation in juneau-commons. It 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.
Format-side concerns (wire-format overrides, dictionary) live on @MarshalledProp in juneau-marshall.
This annotation was previously named @Beanp. Usages of @Beanp should be updated to @BeanProp
(in org.apache.juneau.commons.bean).
Property Name: name / value
The @BeanProp(name) annotation overrides the name of the bean property.
public class MyBean {
@BeanProp(name="Bar")
public String getFoo() {...}
}
The @Name annotation is a shortcut for specifying a bean property name:
public class MyBean {
@Name("Bar")
public String getFoo() {...}
}
The @BeanProp(value)
annotation is a synonym for name. Use it when you are only specifying a name so the annotation is more
concise:
// These two annotations are equivalent:
@BeanProp(name="foo")
@BeanProp("foo")
If the beanFieldVisibility setting on the marshalling context excludes this field (e.g. the visibility is
set to the default of PUBLIC but the field is PROTECTED), this annotation can be used to force the field to
be identified as a property.
public class MyBean {
@BeanProp
protected String getFoo() {...}
}
Dynamic Properties: name="*"
The bean property named * is the designated "dynamic property" which allows for "extra" bean properties
not otherwise defined.
This is similar in concept to the Jackson @JsonGetterAll and @JsonSetterAll annotations but generalized
for all supported marshall languages.
The primary purpose is for backwards compatibility in parsing newer streams with additional information into
older beans.
The following shows various ways of using 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, a String and Object.
public class BeanWithDynaMethods {
@BeanProp(name="*")
public Map<String,Object> getMyExtraStuff() {
...
}
@BeanProp(name="*")
public void setAnExtraField(String name, Object value) {
...
}
}
// Option #3 - Getter only.
// Properties will be added through the getter.
public class BeanWithDynaGetterOnly {
@BeanProp(name="*")
public Map<String,Object> getMyExtraStuff() {
...
}
}
If you're not interested in these additional properties, you can use the
ignoreUnknownBeanProperties setting to ignore values that don't fit into existing properties.
Property Type: type
The @BeanProp(type) annotation identifies a specialized class type for a generalized property. Normally the type is inferred through reflection of the field type or getter return type. However, 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 class with a no-arg constructor.
public class MyBean {
// Identify concrete type as a HashMap.
@BeanProp(type=HashMap.class)
public Map p1;
}
Generic Type Parameters: params
The @BeanProp(params) annotation is for bean properties of type map or collection. It identifies the class types of the contents of the bean property object when the general parameter types are interfaces or abstract classes.
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;
}
Read-Only Properties: ro
The @BeanProp(ro) annotation identifies a property as read-only. Serializers will serialize such properties as usual, but parsers will silently ignore them.
public class MyBean {
@BeanProp(ro="true")
public float price;
}
Marking record components as read-only is not supported during parsing. Because records are immutable, all components must be provided to the canonical constructor.
Write-Only Properties: wo
The @BeanProp(wo) annotation identifies a property as write-only. Parsers will parse such properties as usual, but serializers will silently ignore them.
public class MyBean {
@BeanProp(wo="true")
public float price;
}
Element Type: elementType
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.
public class OrderCollection {
// Stream property - element type cannot be inferred at runtime due to erasure
@BeanProp(elementType=Order.class)
public Stream<Order> getOrders() { ... }
}
Bean Factory: factory
Specifies a BeanFactory class to use when instantiating the value of this specific bean property,
overriding the class-level @BeanType(factory) if present.
public class MyBean {
@BeanProp(factory=ItemChannelFactory.class, elementType=Item.class)
public BeanChannel<Item> getItems() { ... }
}
Annotation Inheritance
@BeanProp and @Name annotations are automatically inherited when bean
property methods (getters, setters, extraKeys) are overridden in subclasses.
This feature is particularly useful for fluent APIs where you want to override setters to change the return type without needing to re-annotate every method.
// Parent class with annotated property
public class Parent {
private List<String> children;
@BeanProp("c") // Custom property name
public List<String> getChildren() {
return children;
}
public Parent setChildren(List<String> children) {
this.children = children;
return this;
}
}
// Child class with fluent setter override
public class Child extends Parent {
@Override
public List<String> getChildren() {
return super.getChildren();
}
@Override
public Child setChildren(List<String> children) {
// Automatically inherits @BeanProp("c") from parent.
// Property name remains "c" — no re-annotation needed.
super.setChildren(children);
return this; // Return type changed for fluent chaining
}
}
If you want to override a method and use a different property name, re-annotate explicitly:
public class Child extends Parent {
@Override
@BeanProp("childList") // Explicit new name takes precedence
public Child setChildren(List<String> children) {
super.setChildren(children);
return this;
}
}
- @BeanType Annotation - Class-level bean-modeling annotation.
- Java Beans Support - Overview of bean property detection.