Skip to content

Data Annotations


Target: FIELD

Turns a field into a search-as-you-type lookup. search provides the list of matching options for a given query; label resolves the human-readable display label for the stored ID value. Setting bubble to true propagates the selection event to the parent component.

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Lookup {
Class<? extends LookupOptionsSupplier> search() default LookupOptionsSupplier.class;
Class<? extends LabelSupplier> label() default LabelSupplier.class;
boolean bubble() default false;
}
AttributeTypeDefaultDescription
searchClass<LookupOptionsSupplier>—Provider that returns matching options for a search term
labelClass<LabelSupplier>—Provider that returns the display label for a stored ID
bubblebooleanfalsePropagate the selection event to the parent component
// The field stores an ID; @Lookup resolves the display label
@Lookup(search = CustomerSearchService.class, label = CustomerLabelService.class)
String customerId;
// CustomerSearchService implements LookupOptionsSupplier
// CustomerLabelService implements LabelSupplier

Target: FIELD

Embeds a child CRUD collection inside a parent form. Mateu renders the field as an inline, editable list of child records linked to the parent through a foreign key.

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Composition {
Class<? extends Named> targetClass();
Class<? extends CompositionCrudStore> repositoryClass();
String foreignKeyField();
}
AttributeTypeDefaultDescription
targetClassClass<Named>—The child entity class
repositoryClassClass<CompositionCrudStore>—Store that manages the child records
foreignKeyFieldString—Name of the foreign key field on the child entity
public class InvoiceForm {
String invoiceId;
@Composition(
targetClass = InvoiceLine.class,
repositoryClass = InvoiceLineRepository.class,
foreignKeyField = "invoiceId"
)
List<InvoiceLine> lines;
}

Target: FIELD

Maps one field value to another at display time using a list of @ValueMapping from→to pairs. If no mapping matches, defaultValue is shown.

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MappedValue {
ValueMapping[] mappings();
String defaultValue();
}
AttributeTypeDescription
mappingsValueMapping[]Array of from→to substitution rules
defaultValueStringValue shown when no mapping matches
@MappedValue(
mappings = {
@ValueMapping(from = "M", to = "Male"),
@ValueMapping(from = "F", to = "Female"),
@ValueMapping(from = "X", to = "Non-binary")
},
defaultValue = "Unknown"
)
String gender;

A single mapping entry used inside @MappedValue. Substitutes the raw value from with the display string to.

public @interface ValueMapping {
String from();
String to();
}
AttributeTypeDescription
fromStringThe raw stored value to match
toStringThe display string to substitute

Target: FIELD

Automatically fills the field with a generated value using the provided ValueGenerator implementation when a new record is created.

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface GeneratedValue {
Class<? extends ValueGenerator> value();
}
AttributeTypeDescription
valueClass<ValueGenerator>The generator implementation to use
public class OrderForm {
@PrimaryKey
@GeneratedValue(UuidGenerator.class)
String orderId;
String customer;
}

Custom generator:

public class InvoiceNumberGenerator implements ValueGenerator {
@Override
public Object generate() {
return "INV-" + System.currentTimeMillis();
}
}

Target: FIELD, PARAMETER

Meant to provide the concrete generic type when Java type erasure hides it at runtime.

public @interface GenericClass {
Class clazz();
}
AttributeTypeDescription
clazzClassThe concrete type argument (e.g. MyDto.class)

No attributes. Marks a field as a sub-resource reference. Mateu renders it as a navigable link to a separate resource page rather than embedding it inline.

public @interface Subresource {}
public class CustomerForm {
String customerId;
String name;
@Subresource
InvoiceListPage invoices;
}

Target: FIELD

Controls how a field is rendered in read-only / list view. Unlike @Stereotype, which controls the input widget in edit mode, @Representation governs the display-only presentation.

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Representation {
FieldStereotype value();
}

See field-types for the full FieldStereotype enum reference.


Label an enum constant with @Label when its name does not say it:

public enum InvoiceStatus {
DRAFT,
@Label("Sent to customer")
SENT,
PAID
}

What an enum constant is called without a label

Section titled “What an enum constant is called without a label”

A constant needs no annotation when its name says it. Mateu calls it, in order:

  1. by its @Label (@Label("Mark as no-show") NO_SHOW);
  2. by its toString(), when the enum overrides it;
  3. by its name humanized: CHECK_OUT → “Check out”, CheckOut → “Check out”, ROOM1 → “Room 1”.

So in the example above, DRAFT and PAID need no annotation (“Draft”, “Paid”). The .NET ([Label] on the member) and Python (the enum’s own __str__) backends follow the same rule.

The same names are used in listing and grid cells: an enum column carries its labels on the wire (GridColumn.valueLabels) and every renderer shows “In house” instead of IN_HOUSE — in a status badge too, whose tone is still picked by the raw value. The row itself keeps the raw constant, so sorting, filtering, row selection and inline editing work on it exactly as before.


Target: FIELD

Controls how radio-button or checkbox options are laid out by specifying the number of columns.

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OptionsLayout {
int columns() default 1;
}
AttributeTypeDefaultDescription
columnsint1Number of columns used to display options
public class SurveyForm {
@UseRadioButtons
@OptionsLayout(columns = 3)
SatisfactionLevel rating;
}