Attribute Pipeline
Purpose
The attribute pipeline transforms WildFly management model metadata into view and form items for the UI. It bridges the gap between raw attribute descriptions (metadata only from the management model) and interactive UI controls that display values and enable editing.
The pipeline solves the core problem of rendering heterogeneous WildFly attributes — simple scalars, complex nested objects, sibling groups, and composite structures — through a consistent, extensible architecture.
Design
The pipeline uses a two-tier architecture: handlers claim and produce items for known patterns, while providers handle unclaimed attributes and child attributes delegated by handlers.
Handlers
AttributeHandlers scan the attribute pool in priority order, claiming groups of related attributes into AttributeMatches. Each handler both claims and produces items for its matches. Handlers bridge the description world (metadata only) and the value world (resolved snapshots with current values and RBAC state).
Registered handlers in priority order:
| Priority | Handler | Pattern | Attributes |
|---|---|---|---|
| 1 | CredentialReferenceHandler | OBJECT with {store, alias, clear-text} | 49 |
| 2 | TimeUnitHandler | OBJECT with {time, unit} | 8 |
| 3 | FileHandler | OBJECT with {path, relative-to} | 9 |
| 4 | PathRelativeToHandler | sibling path + relative-to STRING pairs | 31 |
| 5 | MapHandler | OBJECT with simple scalar VALUE_TYPE | 178 |
| 6 | ListSimpleRecordHandler | LIST of OBJECT with all simple/LIST-of-simple sub-attributes | 27 |
| 7 | FlatteningHandler | simpleRecord OBJECTs (all simple sub-attributes) | 111 |
Providers
ItemProviders handle unclaimed attributes and child attributes delegated by handlers. Providers operate in the value world only — they receive already-resolved ResolvedAttributes. First match wins.
Registered providers in order:
| Priority | Provider | Pattern | Attributes |
|---|---|---|---|
| 1 | RelativeToProvider | standalone relative-to attributes (form only) | 1 |
| 2 | DefaultProvider | type-based dispatch catch-all | 5,384 |
Type Flow
The pipeline operates through distinct type transformations:
AttributeMatch lives in the description world. ResolvedAttribute lives in the value world. Handlers bridge the two — they receive matches and context, perform resolution, and either produce items directly or delegate children to the provider chain via Pipeline.viewItem/formItem.
Use Cases
The pipeline handles four distinct attribute patterns:
| Pattern | Match | Resolution | Items | Example |
|---|---|---|---|---|
| Single attribute | Unclaimed | 1 resolved | 1 item, 1 resolved | enabled (STRING) |
| Composite OBJECT | 1 OBJECT desc | 1 parent + n children | 1 composite item | credential-reference |
| Flattened simple-record | 1 OBJECT desc | 1 parent + n children | n items with FQN paths | {foo, bar} OBJECT |
| Sibling group | n descs | n resolved | 1 composite item | path + relative-to |
| List of simple records | 1 LIST desc | 1 parent, n entries × m children | 1 table item | realms, global-modules |
Single Attribute
A standalone STRING, BOOLEAN, INT, etc.
Match: no handler claims it → unclaimed
Resolve: Pipeline resolves → ResolvedAttribute(enabled)
Provider: DefaultProvider → SwitchControl / StringControl / etc.
Item: 1 item, 1 ResolvedAttributeComposite OBJECT
An OBJECT kept as a single unit (e.g., credential-reference).
Match: CredentialReferenceHandler claims it → AttributeMatch([credential-reference])
Handler: resolves parent, derives children (store, alias, clear-text) via parent.child()
delegates children to provider chain → DefaultProvider creates child items
wraps in composite CredentialReferenceViewItem / CredentialReferenceControl
Item: 1 composite itemFlattened Simple-Record OBJECT
An OBJECT with all simple sub-attributes, flattened into individual items.
Match: FlatteningHandler claims it → AttributeMatch([my-record])
Handler: resolves parent (RBAC captured), derives children:
→ parent.child("foo") → ResolvedAttribute(foo) with fqn="my-record.foo"
→ parent.child("bar") → ResolvedAttribute(bar) with fqn="my-record.bar"
Each child inherits the parent's readable/writable state.
Delegates each child to Pipeline.viewItem/formItem → provider chain.
Items: n items, each holds 1 ResolvedAttribute with FQN pathSibling Group
Multiple sibling attributes that semantically belong together (e.g., path + relative-to).
Match: PathRelativeToHandler claims both → AttributeMatch([path, relative-to])
Handler: resolves both attributes against context
creates composite PathRelativeToViewItem / PathRelativeToFormItem
Item: 1 composite item, holds 2 ResolvedAttributesList of Simple Records
A LIST where each entry is an OBJECT with all simple sub-attributes.
Match: ListSimpleRecordHandler claims it → AttributeMatch([realms])
Handler: resolves parent, iterates list entries via listEntry()
for each entry, delegates children to provider chain via child().detachFromParent()
renders as compact table (view) or editable table with modal form (edit)
Item: 1 table item, n entries × m childrenCurrent State & Open Work
Coverage (WildFly 40)
Total attributes by storage and type (from model graph analysis):
| Storage | STRING | BOOLEAN | INT | LONG | DOUBLE | OBJECT | LIST | BYTES | Total |
|---|---|---|---|---|---|---|---|---|---|
| Configuration | 1,628 | 1,062 | 613 | 285 | 19 | 303 | 207 | 1 | 4,118 |
| — deprecated | 96 | 72 | 10 | 1 | — | 8 | 21 | — | 208 |
| — active | 1,532 | 990 | 603 | 284 | 19 | 295 | 186 | 1 | 3,910 |
| Runtime | 500 | 318 | 333 | 353 | 17 | 64 | 100 | — | 1,685 |
Configuration OBJECT breakdown (303 total, 8 deprecated):
| Category | Count | Deprecated | Active | Handler |
|---|---|---|---|---|
| Simple scalar value-type (maps) | 178 | 0 | 178 | MapHandler |
| Simple record (all simple sub-attrs) | 111 | 0 | 111 | FlatteningHandler |
| Complex (nested LIST/OBJECT children) | 14 | 8 | 6 | Not yet covered |
Configuration LIST breakdown (207 total, 21 deprecated):
| Category | Count | Deprecated | Active | Handler |
|---|---|---|---|---|
| LIST of simple type (STRING, INT, etc.) | 173 | 21 | 152 | DefaultProvider |
LIST of simple records (incl. LIST<simple> sub-attrs) | 27 | 0 | 27 | ListSimpleRecordHandler |
LIST with nested LIST<OBJECT> | 5 | 0 | 5 | Not yet covered |
| LIST with nested OBJECT | 2 | 0 | 2 | Not yet covered |
The pipeline covers ~99% of simple/scalar attributes and ~95% of all configuration attributes. Excluding deprecated attributes (208 of 4,118), active coverage rises to ~97% with only 13 active uncovered attribute definitions remaining.
Runtime attributes are read-only, so even uncovered attributes render acceptably as plain text or JSON display.
Planned Handlers
The following handlers are planned but not yet implemented:
| Handler | Pattern | Count | Deprecated | Active | Priority | Examples |
|---|---|---|---|---|---|---|
| List of Nested Complex Lists | LIST of OBJECT with nested LIST<OBJECT> sub-attributes | 5 | 0 | 5 | MEDIUM | mechanism-configurations, permission-mappings, constant-headers, services |
| List of Nested Objects | LIST of OBJECT with nested OBJECT sub-attributes | 2 | 0 | 2 | MEDIUM | server-auth-modules, principal-query |
| Complex Object | Complex/recursive OBJECTs with nested LIST/OBJECT children | 14 | 8 | 6 | LOW | filter (logging, 8 resources, all deprecated — use filter-spec), identity-mapping, jwt, any/not (interface), attributes (console-access-log), new-item-template |
The ListSimpleRecordHandler now covers LIST attributes with all-simple sub-attributes including LIST<simple> sub-attributes (e.g., role-map with its to: LIST<STRING>), pushing coverage past 95%. Excluding deprecated attributes, active coverage is ~97% with only 13 active uncovered attribute definitions remaining.
Implementation Details
The pipeline source code is in ui/src/main/java/org/jboss/hal/ui/resource/pipeline/, with comprehensive package-level Javadoc describing the architecture and data flow. Each handler documents:
- Pattern recognition logic
- Attribute claiming rules
- Resolution strategy
- Item production approach
- Covered attributes with examples