YAML Reference
The dynamic model is serialized as YAML under a model: root key. This page documents the schema in full: every field, its type, whether it is required, its default value, and the rules that govern it. For task-oriented guidance, see Defining the Model and Views and Menu Items.
Model
The model root contains these top-level fields:
| Field | Type | Required | Notes |
|---|---|---|---|
|
string |
no |
Java package for generated dynamic entity, enum, and view classes. If omitted or blank, the effective value is the last Jmix module base package plus |
|
list |
no |
Dynamic enum definitions. Missing or |
|
list |
no |
Static entity extensions and dynamic entity definitions. Missing or |
Names and Resolution
Entity definitions are matched by Jmix entity name:
-
If an entity with
namealready exists in metadata, the definition extends that static entity with dynamic attributes, validation, uniqueness, or view overrides. -
If no metadata entity exists, Dynamic Model creates a dynamic entity with the same Jmix entity name and a generated Java class named
<effective basePackage>.<name>.
Use Java-like names for dynamic entities, attributes, enum classes, and enum values. Generated database identifiers are normalized automatically:
-
camel case is split to upper underscore names, for example
loyaltyLevelbecomesLOYALTY_LEVEL; -
unsupported characters are replaced with underscores;
-
reserved words receive a trailing underscore, for example
userbecomesUSER_; -
identifiers exceeding the DBMS limit are shortened with an 8-character hash.
Localization Values
Most captions use a plain locale-to-message map:
messages:
en: "Loyalty level"
de: "Treuestufe"
Some fields are localized values and accept either a plain string:
viewTitle: "Benefit"
or a locale map:
viewTitle:
en: "Loyalty levels"
de: "Treuestufen"
Locale keys must be non-blank and map to strings. At runtime, the exact locale is preferred, then the language-only locale, then the first map value.
Enumerations
Dynamic enumerations are declared in model.enumerations:
enumerations:
- name: "CustomerGrade"
messages:
en: "Customer grade"
values:
- name: "PLATINUM"
id: "30"
messages:
en: "Platinum"
- name: "GOLD"
id: "20"
messages:
en: "Gold"
- name: "BRONZE"
id: "10"
messages:
en: "Bronze"
Enum fields:
| Field | Type | Required | Notes |
|---|---|---|---|
|
string |
yes |
Short class name or fully qualified class name. Short names are resolved against |
|
list |
yes |
Must contain at least one value. |
|
map |
no |
Captions for the enum class. |
Enum value fields:
| Field | Type | Required | Notes |
|---|---|---|---|
|
string |
yes |
Java enum constant name. |
|
string |
yes |
Stored enum ID. All IDs in one dynamic enum must be homogeneous: either all parse as 32-bit integers or all are non-integer strings. |
|
map |
no |
Captions for this enum value. |
Dynamic enums implement EnumClass<Integer> when all IDs are integer strings, otherwise EnumClass<String>.
Attribute references to enums use the enumeration field:
- name: "grade"
enumeration: "CustomerGrade" # short name, resolved via base package
messages:
en: "Grade"
Static enums are also supported if the class implements EnumClass. Use a fully qualified class name, or a short name when the enum class is in basePackage. Enum DB mapping supports both integer IDs and string IDs.
Entities
Entity definitions are declared in model.entities:
- name: "Benefit"
messages:
en: "Benefit"
attributes:
- name: "name"
javaClass: "java.lang.String"
instanceName: true
messages:
en: "Name"
views:
- type: "detail"
viewId: "Benefit.detail"
viewTitle: "Benefit"
descriptor:
template: "default"
| Field | Type | Required | Notes |
|---|---|---|---|
|
string |
yes |
Jmix entity name. An existing metadata name means a static entity extension; otherwise a dynamic entity is created. |
|
string |
no |
Physical JPA data store for dynamic entities. Blank and |
|
list |
no |
Dynamic attributes. Missing or |
|
list |
no |
Named entity-level unique constraints. |
|
list |
no |
Entity-owned UI views. |
|
object |
no |
Entity CRUD role grants. Supported only for dynamic entities. |
|
object |
no |
Entity-level validation constraints. |
|
map |
no |
Entity captions. |
Dynamic entity tables use the configurable jmix.dynmodel.dynamic-entity-table-prefix prefix, default DYN_. Static entity dynamic attributes are stored in side tables using jmix.dynmodel.static-entity-table-prefix, default DYN_. Static side tables are created in the same physical store as the static owner entity.
Attributes
Every attribute must define exactly one kind:
-
datatype:
javaClass; -
reference:
entityName; -
enum:
enumeration.
- name: "Customer"
attributes:
- name: "taxId"
javaClass: "java.lang.String"
length: 20
required: true
unique: true
validation:
constraints:
- annotation: "Pattern"
parameters:
regexp: "^[A-Z0-9-]+$"
message:
en: "Tax ID can contain uppercase letters, digits and dashes only"
messages:
en: "Tax ID"
| Field | Type | Required | Notes |
|---|---|---|---|
|
string |
yes |
Attribute name. |
|
string |
kind |
Java class for datatype attributes. See supported values below. |
|
string |
kind |
Target Jmix entity name for references and collections. |
|
string |
kind |
Dynamic or static enum name. Short names are resolved through |
|
integer |
no |
Length for strings, URI values, byte arrays, and string-ID enums. |
|
boolean |
no |
LOB indicator. Supported only for |
|
boolean |
no |
Adds mandatory metadata and a default-group |
|
boolean |
no |
Shorthand for a single-attribute unique constraint named |
|
boolean |
no |
Marks the attribute as an instance-name property. If several attributes are marked, the first one is used and later ones are ignored with a warning. |
|
boolean |
no |
Makes an |
|
object |
no |
Makes the attribute read-only and non-persistent. |
|
object |
no |
Attribute-level constraints. Not allowed on calculated attributes. |
|
object |
no |
Attribute view/modify grants. |
|
map |
no |
Attribute captions. |
Supported javaClass Values
Persistent datatype attributes are mapped to SQL types by the framework. Use these values when writing YAML manually:
| YAML value | Java type | Default SQL mapping |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DB-specific UUID type |
Notes:
-
The serializer stores Java
Class#getName()values. For a byte array this is[B; copy the serialized value if unsure. -
Other Java classes are not supported by Dynamic Model storage unless DB type mapping is extended.
DB-specific deviations:
| Type | HSQLDB / H2 | PostgreSQL | MySQL / MariaDB | SQL Server | Oracle |
|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
References
Single-valued references use entityName:
- name: "loyaltyLevel"
entityName: "LoyaltyLevel"
messages:
en: "Loyalty level"
Rules:
-
The target must resolve to a dynamic entity declared in the model or to an existing static entity.
-
Dynamic references store the target primary key value.
-
Static targets with composite primary keys are not supported.
-
Owner and target must be in the same physical store.
Collections
Collection attributes are ordered composition lists:
- name: "benefits"
entityName: "Benefit"
collection: true
messages:
en: "Benefits"
Rules:
-
entityNameis required. -
The target must be a dynamic entity.
-
javaClass,enumeration,lob, andinstanceNameare not supported. -
Collections cannot participate in unique constraints.
-
Owner and target must be in the same physical store.
-
Static owners with composite primary keys are not supported.
Dynamic Model creates internal child properties for the inverse owner reference and order column. They are not written to YAML.
Calculated Attributes
Calculated attributes are read-only, non-persistent properties evaluated on access:
- name: "publicSummary"
javaClass: "java.lang.String"
calculated:
evaluator: "spel"
expression: "(name ?: '') + ': ' + (description ?: '')"
dependsOn:
- "name"
- "description"
messages:
en: "Public summary"
| Field | Type | Required | Notes |
|---|---|---|---|
|
string |
no |
Evaluator name returned by a |
|
string |
yes |
Evaluator-specific expression. The built-in |
|
list |
no |
Immediate property names to load with the calculated attribute. Dotted paths are rejected. Missing or |
Rules:
-
A calculated attribute must declare exactly one result type using
javaClassorenumeration. -
entityName,collection,required,validation, and uniqueness are not supported. -
lob: trueis only a UI metadata hint and still requiresjavaClassto bejava.lang.Stringorbyte[]. -
Dependencies must exist on the same entity, either in the current model or in existing metadata.
-
Cycles between calculated attributes in one entity are rejected.
-
Changing an existing stored attribute to calculated, or an existing calculated attribute to stored, is not supported. Changing the calculated result type is also not supported.
The built-in SpEL evaluator allows metadata-aware property reads and registered DynamicCalculatedAttributeFunction functions. It does not expose Spring beans, T(…), constructors, arbitrary method calls, reflection, classloader access, or infrastructure APIs.
Attribute Validation
Attribute validation is declared under attributes[].validation.constraints:
validation:
constraints:
- annotation: "Pattern"
parameters:
regexp: "^[A-Z0-9-]+$"
message:
en: "Tax ID can contain uppercase letters, digits and dashes only"
Constraint fields:
| Field | Type | Required | Notes |
|---|---|---|---|
|
string |
yes |
Constraint alias. See supported aliases below. |
|
map |
no |
YAML scalar/list/object values. Parameter names depend on the constraint. Missing becomes an empty map. |
|
list |
no |
Group aliases or fully qualified validation group class names. Missing means |
|
localized value |
no |
Plain string or locale map. |
Supported groups:
-
Default; -
UiComponentChecks; -
UiCrossFieldChecks; -
RestApiChecks; -
fully qualified class names resolvable by
Class.forName().
Supported attribute constraints:
| Alias | Applies to | Parameters |
|---|---|---|
|
any attribute |
none |
|
strings, collections, arrays |
none |
|
strings |
none |
|
strings, collections, arrays |
|
|
strings |
|
|
numeric |
|
|
numeric |
|
|
numeric |
|
|
numeric |
|
|
numeric |
|
|
numeric |
none |
|
numeric |
none |
|
numeric |
none |
|
numeric |
none |
|
date/time |
none |
|
date/time |
none |
|
date/time |
none |
|
date/time |
none |
|
strings |
|
|
strings |
none |
|
booleans |
none |
|
booleans |
none |
Validation uses Bean Validation null semantics: null is valid unless the rule is NotNull, NotEmpty, NotBlank, AssertTrue, or AssertFalse.
required: true is equivalent to mandatory UI metadata plus a default-group NotNull rule. Validation metadata does not create DB constraints.
Entity Validation
Entity-level validation is declared under entities[].validation.constraints:
validation:
constraints:
- name: "discountDescriptionRequired"
target: "entity"
type: "expression"
evaluator: "spel"
expression: "discount == null || description != null"
attributes:
- "discount"
- "description"
path: "description"
groups:
- "UiCrossFieldChecks"
- "RestApiChecks"
message:
en: "Description is required when discount is specified"
| Field | Type | Required | Notes |
|---|---|---|---|
|
string |
no |
Constraint name for diagnostics. |
|
string |
yes |
Must be |
|
string |
yes |
|
|
string |
expression |
Built-in expression evaluator is |
|
string |
expression |
Must evaluate to |
|
string |
bean |
Name returned by a |
|
list |
no |
Participating attribute names. Each name must exist in the model or metadata. |
|
string |
no |
Violation property path. Blank means a bean-level violation. |
|
list |
no |
Same group aliases as attribute validation. |
|
localized value |
no |
Plain string or locale map. |
Expression constraints use the same restricted SpEL property access approach as calculated attributes. Bean constraints delegate to application DynamicModelConstraintValidator beans.
Unique Constraints
Single-attribute uniqueness:
unique: true
Composite uniqueness:
uniqueConstraints:
- name: "customerCountryTaxIdUnique"
attributes:
- "countryCode"
- "taxId"
message:
en: "Tax ID must be unique within a country"
| Field | Type | Required | Notes |
|---|---|---|---|
|
string |
yes |
Logical constraint name. Must be non-blank and unique within the entity. The physical DB name is generated from the table name plus this value. |
|
list |
yes |
At least one direct dynamic attribute. Duplicate names are rejected. |
|
localized value |
no |
Violation message. |
Rules:
-
attributes[].unique: trueis normalized to a named entity-level constraint before comparison and DDL planning. -
Only direct persistent single-valued dynamic attributes can participate.
-
Calculated attributes, collections, and LOB attributes are rejected.
-
Static soft-deletable owners are not supported.
-
Applying a new unique constraint fails if existing rows already contain duplicates.
-
Nullable uniqueness follows the target DBMS behavior.
Resource Roles
Dynamic resourceRoles declarations create additive resource policies at runtime. Omitted declarations do not grant access. Roles listed in jmix.dynmodel.security.full-access-roles grant full access to all dynamic model resources; the default is system-full-access.
Role codes must be non-blank. Missing role codes are logged and do not grant access.
Entity-level CRUD grants are supported only for dynamic entities:
resourceRoles:
read:
- "employee"
- "manager"
create:
- "manager"
update:
- "manager"
delete:
- "manager"
Attribute grants are supported on dynamic attributes of both static and dynamic entities:
- name: "countryCode"
javaClass: "java.lang.String"
length: 2
resourceRoles:
view:
- "employee"
- "manager"
modify:
- "manager"
messages:
en: "Country code"
View and menu grants are lists:
views:
- type: "list"
viewId: "LoyaltyLevel.list"
viewRoute: "loyalty-levels"
viewTitle:
en: "Loyalty levels"
de: "Treuestufen"
templateParams:
includeProperties: ["name", "discount"]
excludeProperties: ["publicSummary"]
resourceRoles:
- "employee"
- "manager"
menuItem:
parentMenu: "application"
insertBefore: "Customer.list"
title:
en: "Loyalty levels"
resourceRoles:
- "employee"
- "manager"
descriptor:
template: "default"
Views
Views are declared under entities[].views.
views:
- type: "list"
viewId: "LoyaltyLevel.list"
viewRoute: "loyalty-levels"
viewTitle:
en: "Loyalty levels"
de: "Treuestufen"
templateParams:
includeProperties: ["name", "discount"]
excludeProperties: ["publicSummary"]
resourceRoles:
- "employee"
- "manager"
menuItem:
parentMenu: "application"
insertBefore: "Customer.list"
title:
en: "Loyalty levels"
resourceRoles:
- "employee"
- "manager"
descriptor:
template: "default"
View fields:
| Field | Type | Required | Notes |
|---|---|---|---|
|
string |
dynamic entities |
|
|
string |
yes |
Unique view ID. Dynamic and static view declarations should set it explicitly. |
|
string |
no |
Dynamic entity route segment. Defaults to a slug made from |
|
localized value |
no |
Dynamic entity view title. Static entity views do not support this field. |
|
map |
no |
Dynamic entity template parameters. Static entity views do not support this field. |
|
list |
no |
Role codes that can open the view. Static entity views do not support this field. |
|
object |
no |
Dynamic entity menu item. Static entity views do not support this field. |
|
object |
static entities |
Descriptor declaration. Dynamic entity views can omit it to use the default template. Static entity views must provide |
|
string |
no |
Dynamic list view lookup component ID. Default is |
|
string |
no |
Dynamic detail view edited entity container ID. Default is |
Dynamic Entity Views
Rules:
-
typemust belistordetail. -
viewIdmust be set explicitly and must be unique. -
If
viewRouteis omitted, it is generated fromviewIdby lowercasing and replacing non-alphanumeric sequences with-. -
Detail routes automatically append
/:id; thereforeviewRouteitself must not end with/:id. -
The first declared list view becomes the primary list view for the dynamic entity. The first declared detail view becomes the primary detail view.
-
descriptormay be omitted, usetemplate: "default", use a custom template resource path, or provide literalsource. -
If
descriptor.sourceis used, it must be valid XML with root<view xmlns="http://jmix.io/schema/flowui/view">. -
Explicit list descriptors must contain the lookup component ID, default
dataGrid. -
Explicit detail descriptors must contain the edited entity container ID, default
entityDc.
Default templates are:
-
io/jmix/flowui/view/template/list-view.ftlfor list views; -
io/jmix/flowui/view/template/detail-template.ftlfor detail views.
templateParams is a YAML object passed to descriptor template rendering. Dynamic Model does not define a fixed schema for it; supported keys depend on the selected template. For example, a template can consume list-of-string property filters:
templateParams:
includeProperties: ["name", "discount"]
excludeProperties: ["publicSummary"]
Static Entity View Overrides
Static entity view declarations override the XML descriptor of an already registered view:
- viewId: "Customer.list"
descriptor:
source: |
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<view xmlns="http://jmix.io/schema/flowui/view"
extends="com/company/sample/view/customer/customer-list-view.xml">
<layout>
<dataGrid id="customersDataGrid">
<columns>
<column property="taxId"/>
</columns>
</dataGrid>
</layout>
</view>
Rules:
-
viewIdis required and must reference a registered static view. -
typemay be omitted; it is inferred from the controller class. -
Only
descriptor.sourceis supported. -
descriptor.template,viewRoute,viewTitle,templateParams,resourceRoles,menuItem,lookupComponentId, andeditedEntityContainerIdare rejected. -
The generated controller subclasses the current registered controller and preserves its route.
Descriptor
descriptor must contain exactly one of:
descriptor:
template: "default"
or:
descriptor:
source: |
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<view xmlns="http://jmix.io/schema/flowui/view"
extends="com/company/sample/view/customer/customer-list-view.xml">
<layout>
<dataGrid id="customersDataGrid">
<columns>
<column property="taxId"/>
</columns>
</dataGrid>
</layout>
</view>
Menu
menuItem fields:
| Field | Type | Required | Notes |
|---|---|---|---|
|
string |
yes |
Existing or new parent menu ID. If not found, a root menu with this ID is created. |
|
string |
no |
Insert before a sibling menu ID when found; otherwise append. |
|
localized value |
no |
Defaults to the view title when omitted. |
|
list |
no |
Role codes that can access the menu item. |
Detail view menu items receive the route parameter id=new.