TopLogic - the automated application engine
  • Releases
  • Dokumentation
  • Github
  • Discord
  1. Home
  2. Releases
  3. TL_8.0.0-alpha11
  4. Migration guide

8.0.0-alpha11
TopLogic Release

2026-10-20

Markdown version, e.g. for an LLM updating an application.

Migrating a TopLogic application from 8.0.0-alpha10 to 8.0.0-alpha11

Audience: an AI coding agent (or developer) upgrading a TopLogic application project. Sources: release notes https://dev.top-logic.com/tl/content/releases/TL_8.0.0-alpha11/ and the TopLogic Trac tickets of milestone TL_8.0.0-alpha11 (ticket numbers given as #NNNNN; the per-ticket page is https://dev.top-logic.com/tl/content/releases/TL_8.0.0-alpha11/NNNNN/).

How to use this document

  1. Work through the sections in order. Section 1 first (the project must build); the rest in any order.
  2. Every step has a Detect line: run the search in the application's source tree. No hit → the step does not apply, skip it. Do not invent changes for steps that do not apply.
  3. Many changes surface only as configuration errors at application start or when a view is loaded. After migrating, start the application, log in, open every view, and read the log.
  4. The engine ships developer articles in its jars (META-INF/tl-docs/**/*.md). If the tl-mcp tools are available, read them with read_doc (names given as doc:<name>).
  5. If the application comes from TopLogic 7.10 / 7.11, follow the upgrade guide doc:upgrade-7.11-to-8.0 first (#29790); it covers all 8.0 changes in the required order and needs Maven 3.8.9 or newer.
  6. If you continue to 8.0.0-alpha12 afterwards: alpha12 changes view scripts again (named arguments, no lambda heads, see the alpha11→alpha12 guide). Still do the alpha11 steps first; they are the basis of the alpha12 rules.

Search commands assume the project root as working directory and GNU grep.


1. Build, wrapper generation, Java API

1.1 Version bump

Set the TopLogic version to 8.0.0-alpha11 (parent tl-parent-app / tl-parent-core version, or the tl.version property).

1.2 Snapshot repository (#29789) — only for SNAPSHOT versions

tl-parent-all no longer declares the TopLogic snapshot repository. An application inheriting the TopLogic parent POMs and building against a TopLogic SNAPSHOT from the TopLogic Nexus must declare it itself (archetype-generated applications already do). Released versions need no change.

<repositories>
  <repository>
    <id>tl-snapshots</id>
    <url>https://dev.top-logic.com/nexus/repository/toplogic-snapshots/</url>
    <releases><enabled>false</enabled></releases>
    <snapshots><enabled>true</enabled></snapshots>
  </repository>
</repositories>
<pluginRepositories>
  <pluginRepository>
    <id>tl-snapshots</id>
    <url>https://dev.top-logic.com/nexus/repository/toplogic-snapshots/</url>
    <releases><enabled>false</enabled></releases>
    <snapshots><enabled>true</enabled></snapshots>
  </pluginRepository>
</pluginRepositories>

Detect: grep -n -e 'SNAPSHOT' -e 'tl-snapshots' pom.xml */pom.xml

1.3 Regenerate the Java wrappers (#29806, #29807) — mandatory if the app uses generated wrappers

Run the wrapper generation (tl:generate-java / the module's generate step) for all application modules, then fix compile errors:

  • #29806: after regeneration, a class that does not specialize tl.element:StructuredElement gets AttributedWrapper as implementation base (before: every top-level class of a module with a singleton extended StructuredElement). Code treating such objects as StructuredElement (casts, getParent(), getChildren()) no longer compiles → correct the code, or let the model class declare the tl.element:StructuredElement generalization it relied on. The XImpl of a class whose primary generalization is a concrete or bound type now extends that type's implementation class (hand-written code unaffected).
  • #29807: factory members for classifier constants are deprecated (still compile). After regenerating, replace their uses (optional, recommended):
Old (deprecated) New
MyFactory.MY_MODULE_STRUCTURE MyFactory.MY_MODULE_MODULE
MyFactory.KO_NAME_A A.TABLE_NAME
MyFactory.MY_ENUM_ENUM MyEnum.TYPE_NAME
MyFactory.FIRST_MY_ENUM_CLASSIFIER MyEnum.FIRST_CLASSIFIER
MyFactory.getMyEnumEnum() MyEnum.type()
MyFactory.getFirstMyEnumClassifier() MyEnum.firstClassifier()

A factory that did not compile because of colliding classifier names compiles after regeneration (colliding legacy aliases are not generated).

Detect: grep -rln -e 'StructuredElement' -e 'getParent()' -e 'getChildren()' --include=*.java src and grep -rn -E '[A-Z][A-Za-z]*Factory\.(KO_NAME_|[A-Z_]+_(ENUM|STRUCTURE|CLASSIFIER)\b|get[A-Za-z]+(Enum|Classifier)\()' --include=*.java src

1.4 Wrapper hierarchy clean-up (#29840) — Java

  • Calls to deleted members of AbstractWrapper, StructuredElementWrapper, WrapperFactory no longer compile (they had no engine callers) → use the replacement or remove.
  • touch() → TLObject.tTouch().
  • handleLoad(), handleDelete(), notifyUpcomingDeletion() are public interface methods of WrapperLifecycle: overrides in application code must be declared public.
  • resolveWrappers, resolveWrappersTyped, resolveLinks, updateOrderedLinkSet are public Wrapper defaults; typed accessors (getString(String), …) and the AbstractBoundWrapper methods are no longer final. Overrides of getValue(String) / setValue(String, Object) or tValue / tUpdate keep working.
  • instanceof AbstractBoundWrapper → BoundObject / BoundWrapper; instanceof AbstractWrapper → Wrapper.

Detect:

grep -rn -e 'touch()' -e 'handleLoad()' -e 'handleDelete()' -e 'notifyUpcomingDeletion' \
  -e 'instanceof AbstractBoundWrapper' -e 'instanceof AbstractWrapper' --include=*.java src

1.5 SimpleDBExecutor (#29838) — Java, rare

The unused methods beginTransaction(CommitHandler), releaseCommitContext(), beginWithDefaultKB() are removed; a SimpleDBExecutor only works with its own transaction started by beginTransaction().

Detect: grep -rn -e 'releaseCommitContext' -e 'beginWithDefaultKB' -e 'SimpleDBExecutor' --include=*.java src


2. Server configuration

2.1 Access parent in the security configuration (#29760) — mandatory if used

(Has a migration section in Trac but is not listed on the release-notes website.) The access parent of a type is no longer set by the attributes access-parent / access-reference of a <class> entry of SecurityConfigurationService, but by an element <access-parent> with exactly one definition. The old attributes are rejected at startup.

Old New
access-parent="container" <access-parent><container/></access-parent>
access-parent="container" access-reference="X" <access-parent><container reference="X"/></access-parent>
access-parent="target" access-reference="X" <access-parent><target reference="X"/></access-parent>
access-parent="self" <access-parent><self/></access-parent>
access-parent="auto" remove the attribute

Also check WEB-INF/autoconf/com.top_logic.model.security.SecurityConfigurationService.config.xml (the "Access rights…" dialog of the coverage view writes there). Java: record TypeCoverage holds the origin of the marks (withoutSecurityOrigin, internalOrigin) instead of booleans; withoutSecurity() and internal() remain. New in this release: a TL-Script function can determine the access parent.

Detect: grep -rn -e 'access-parent=' -e 'access-reference=' -e 'TypeCoverage' .

2.2 OpenAPI server: request body validation (#29785)

Requests whose body does not match the declared schema (incomplete properties with additionalProperties: false, wrong required lists, wrong types) are now answered with 400. A schema that cannot be translated prevents the OpenAPI server from starting. Fix the schema in the OpenAPI server's service configuration to match the actual values, or remove the schema from the parameter if no validation is wanted. Test every operation with real requests.

Detect: grep -rln -e 'OpenApiServer' -e 'request-body' -e 'additionalProperties' --include=*.xml .

2.3 OpenAPI server: empty passwords / API keys (#29784) — no RequiresMigration flag

Basic authentication (technical user) and API-key authentication now ignore a secret with an empty password / key (error in the log naming domain and user/parameter) and always reject requests with an empty password/key. If an environment variable behind an alias is unset (e.g. ${env:api_passwd}), the operation is no longer reachable (500, missing-secret message) instead of being open. Make sure all deployment environments set these variables.

Detect: grep -rn -e 'basic-auth-server-secret' -e 'api-key-server-secret' -e '\${env:' .

2.4 Encrypted configuration values (#29788, #29849) — check, no mandatory step

  • A plain-text value in an @Encrypted property without the prefix unencrypted: fails as before, but the error message no longer contains the value.
  • New encrypted values are written in a new format (prefix {gcm}); an invalid value in this format is a configuration error. Values without prefix are still read with the old method — no migration needed.
  • If startup now fails with an "undecodable value" error for a property, add unencrypted: to plain-text values (typically passwords coming from an environment variable via an alias) or encrypt them properly.

3. React views (*.view.xml)

3.1 Unified drag and drop (#29776) — mandatory if the views use <drag>/<drop>

  • <drag type="module:Type"> no longer exists → <drag kind="…"> with a freely chosen name (e.g. ticket).
  • <drop accept="…"> names drag kinds, not model types: replace accept="module:Type" by the kind of the matching <drag kind>, or omit accept to accept every drag. A restriction to a model type (before: including subtypes) moves into refuse-if, e.g. objects -> !$objects.filter(o -> !$o.instanceOf(`module:Type`)).isEmpty() (the type literal needs both backticks; the published release notes lost the closing one).
  • refuse-if receives the dragged objects as first argument: target -> objects -> … becomes objects -> target -> …. Per drop kind (target attribute of <drop>):
Element target Meaning refuse-if arguments Channels
<table> table onto the table as a whole objects -> target -> reason (target = null) target-channel
<table> row onto a row objects -> target -> reason target-channel
<table> ordered between rows (insertion line); beside the rows = at the end objects -> before -> reason before-channel
<tree> tree / node / ordered as above; ordered = between siblings or as child objects -> parent -> before -> reason (ordered) parent-channel, before-channel
<tree-table> table / row / ordered as for the tree as for the tree as for the tree

A script with fewer parameters ignores the rest (objects -> reason is enough). Misplaced options (e.g. target-channel with ordered, parent-channel in a flat table, target-executability outside row/node) are configuration errors.

  • Several <drop> on one element are checked in declared order (before: row drops before table drops) → reorder mixed drops if needed.
  • Java: DropTarget#dropOnRows() → dropModes(), acceptedTypes() → acceptedKinds(), check(DropEvent) → check(DropRequest), DragSourceControl#dragType() → dragKind() / isDragEnabled(); DropEvent carries a DropLocation instead of target and DropPosition (DropPosition removed).

Detect:

grep -rn --include=*.view.xml -e '<drag' -e '<drop' -e 'refuse-if' .
grep -rn --include=*.java -e 'dropOnRows' -e 'acceptedTypes' -e 'DropEvent' -e 'dragType()' -e 'DropPosition' .

3.2 <adaptive-detail> (#29801)

  • Attribute detail-size of <adaptive-detail> is renamed drawer-size.
  • Content inside <selector> / <detail> that stores personalization (e.g. table column widths) uses a new personalization key; stored values are lost once (inform the user, nothing to migrate).

Detect: grep -rn --include=*.view.xml -e 'detail-size' .

3.3 <text> tone and text classes (#29821)

  • <text tone="accent"> no longer loads (ConfigurationException listing allowed values) → use css-class="tl-type-body-strong".
  • css-class="tlText--strong" has no effect → tl-type-body-strong (label variant: tl-type-label-strong).

Detect: grep -rn --include=*.view.xml -e 'tone="accent"' -e 'tlText--strong' .

3.4 <value-input> with <on-submit> (#29808) — behavior change, no RequiresMigration flag

New attribute submit-on decides when the <on-submit> command of a typed input runs. Text and number inputs are unchanged (Enter). Multi-line text, password and I18N text inputs with <on-submit> ran on every value change before; without submit-on="change" they now run only on their Enter gesture (password) or not at all (multi-line text, I18N text). Add submit-on="change" where the old behavior is needed (the "Apply with Enter" placeholder then disappears).

Detect: grep -rn --include=*.view.xml -B3 -A3 '<on-submit' . (check the input type of each hit)

3.5 Column selection state (#29825) — custom code only

The state of ReactColumnSelectControl changed. Only relevant for code/adapters reading that state; opening the dialog is unaffected. Note: the published migration text ("grouping is one value instead of a flag per entry") describes a superseded design. According to the Trac comments, the dialog that shipped is a layer panel: a row is handle · name · lock · eye (no checkbox), hidden columns stay in place (dimmed), the lock freezes a column (same frozenColumnCount as the freeze handle in the header), and grouping is no longer in the dialog — it is in the column header's context menu. Inspect the actual state contract in the engine source before adapting custom code.

Detect: grep -rn -e 'ReactColumnSelectControl' -e 'TLColumnSelect' .


4. Custom React components / component library (#29787)

Only relevant if the application customizes the React client (e.g. installMui, own adapter modules).

  • installMui({ replace }) selects atomic parts by part name, not control name. An old name fails at startup (unknown component). With replace: 'all' nothing to do.
Old name New part name
'TLButton', 'TLToggleButton' 'Button'
'TLCheckbox' 'Checkbox'
'TLTextInput', 'TLPasswordInput', 'TLNumberInput' 'TextInput' (read-only values: 'FieldValue')
'TLOptionChips' 'Chip'
'TLProgress' 'ProgressBar'
— (new) 'MenuTrigger', 'DisclosureToggle', 'Badge', 'Divider', 'Spinner'
  • Own modules replacing TLButton, TLToggleButton, TLCheckbox, TLTextInput, TLPasswordInput, TLNumberInput, TLOptionChips or TLProgress with replace() must instead replace the part with replacePart() and implement its props contract (ButtonPartProps, CheckboxPartProps, …; see doc:view-layer/parts). Command, keyboard and visibility logic stay in the control.
  • The configured CSS class of text, password and number fields now sits on the outermost element of the field (tl-field-group), not on the <input>: CSS input.myClass → .myClass input.
  • (#29808) The bridge hook useTLTypingField() replaces useTLSubmitOnEnter() and the MUI-internal useTypingField(); custom typed inputs using the old hooks must switch.

Detect:

grep -rn -e 'installMui' -e 'replace(' -e "'TL\(Button\|ToggleButton\|Checkbox\|TextInput\|PasswordInput\|NumberInput\|OptionChips\|Progress\)'" \
  -e 'useTLSubmitOnEnter' -e 'useTypingField' --include=*.ts --include=*.tsx --include=*.js .
grep -rn -E 'input\.[a-zA-Z_-]+' --include=*.css .

5. Stylesheets: design system waves 3b, 4a, 4b, 4c (#29821, #29836, #29866, #29870)

Only relevant if the application has own CSS (or code) addressing the old tl* classes of React controls. General rule: states are attributes, not classes (aria-selected, aria-sort, aria-expanded, aria-current, data-tl-state, data-tl-role, data-tl-tone). The complete old→new tables are in the design system repository, docs/migration/altlast.md, sections "Welle 3b", "Welle 4a", "Welle 4b", "Welle 4c". Rewrite affected rules against the package classes; do not reintroduce old names.

5.1 Table, tree, column selection, text (#29821)

Removed: tlTableView*, tlTreeView*, tlColumnSelect*, tlColumns*, tlText*, tlRelativeTime, tl-pill--<role>, tl-avatar--category-<n>, tl-alert--<status>, tl-alert--closable, tl-select__status. Stylesheets reading --tl-status-error-border / --tl-status-warning-border see a darker line in light mode.

5.2 Dialog, window, drawer, snackbar, notice bar (#29836)

Removed: tlDialog*, tlWindow*, tlDrawer*, tlSnackbar*, tlNoticeBar*, tlOverlay*, tlPhotoCapture__overlay*.

  • Dialog animations: .tlDialog__backdrop--entering / --exiting → .tl-dialog[data-tl-state~="entering"] / [data-tl-state~="exiting"] (the package ships a fade; override on the same state).
  • --tlSnackbar-bg / --tlSnackbar-fg are gone (snackbar is a tinted alert, data-tl-role).
  • .tlOverlay__layer--<anchor> → .tl-overlay__layer--<anchor>.

5.3 App shell, app bar, sidebar, bottom bar (#29866)

Removed: tlAppShell*, tlAppBar*, tlSidebar*, tlBottomBar*, tlDrawerToggle. Small-screen rules read [data-tl-display~="compact"] on .tl-app-shell instead of @media (max-width: 768px). Visible: app bar 48px (40 compact), sidebar a modal drawer on small screens, hamburger only on small screens.

5.4 Layout containers (#29870)

Removed classes tlPanel*, tlCard*, tlStack*, tlGrid*, tlInset, tlBounded, tlItem, tlDeckPane, tlSplitPanel*, tlTileStack*, tlWizard*, tlAdaptiveDetail*, tlViewError*, tlHtml__error; dialog footer tl-dialog__footer is now tl-button-bar. Removed custom properties --page-inset (insets come from tl-inset, tl-inset--panel, tl-inset--card) and --tlGrid-gap; --tl-item-index → --item-index. States: panel [data-tl-state~="minimized"|"maximized"]; split pane [data-tl-state~="collapsed"], all [data-tl-state~="all-collapsed"]; tile stack/wizard transitions [data-tl-state~="entering"|"exiting"|"covered"|"backward"]; wizard steps [data-tl-state~="done"], current [aria-current="step"]; selected item [aria-selected="true"].

Old New
.tlPanel .tl-panel
.tlPanel--card .tl-panel.tl-card
.tlPanel__header, __title, __toolbar, __actions .tl-titlebar, __title (h2), __actions, __buttons
.tlPanel__content .tl-panel__body
.tlPanel__buttonBar, .tl-dialog__footer .tl-button-bar
.tlCard, --outlined, --elevated .tl-card (surface by nesting: --nested, --overlay; no shadow)
.tlStack, .tlGrid, --gap-* .tl-stack, .tl-grid, --gap-compact/default/loose
.tlInset .tl-inset
.tlBounded, .tlItem, .tlDeckPane .tl-bounded, .tl-item, .tl-deck
.tlSplitPanel, __child, __splitter .tl-split, __pane, __handle (role="separator")
.tlTileStack, __frame .tl-tile-stack, __frame
.tlWizard* .tl-wizard*
.tlAdaptiveDetail, __breadcrumb .tl-adaptive-detail, __bar > .tl-breadcrumb
.tlViewError, .tlHtml__error .tl-alert[data-tl-role="error"]

Visible changes (expect, do not "fix"): narrower gaps (1rem), untinted panel heads with non-bold 40px titles, card bodies padded 1rem, no card shadows, split handle as a line (keyboard-movable).

Detect (all of section 5, including css-class values in views):

grep -rn -E 'tl(TableView|TreeView|ColumnSelect|Columns|Text|RelativeTime|Dialog|Window|Drawer|Snackbar|NoticeBar|Overlay|AppShell|AppBar|Sidebar|BottomBar|DrawerToggle|Panel|Card|Stack|Grid|Inset|Bounded|Item|DeckPane|SplitPanel|TileStack|Wizard|AdaptiveDetail|ViewError)|tlHtml__error|tlPhotoCapture__overlay|tl-pill--|tl-avatar--category-|tl-alert--|tl-select__status|tl-dialog__footer|--page-inset|--tlGrid-gap|--tl-item-index|--tlSnackbar-' \
  --include=*.css --include=*.java --include=*.ts --include=*.tsx --include=*.xml --include=*.html .

6. Further notes (no RequiresMigration flag, but possibly relevant)

  • Known regression in alpha11 (#29870 → fixed by #29933 in alpha12): dragging the handle of a <split-panel> with the mouse "runs away" (movement accumulates). Keyboard and double-click reset work. Probably also affects the split of <adaptive-detail>. Not a migration step — do not try to fix it in the application; mention it to the user, or move on to alpha12.

  • Maven (#29790, #29789): Maven 3.8.9 or newer is required. A POM that does not inherit the TopLogic parents should pin its build plugins (e.g. maven-compiler-plugin, maven-resources-plugin); otherwise Maven 3.8.x may bind ancient plugin versions.

  • Model patch (#29800): a class may gain a generalization and override attributes in the same change; the generated SQL migration processors now apply add-generalization before the overrides. If the application worked around this with split migrations, they can stay but are no longer needed.

  • Column type changes (#29846): AlterColumnProcessor / RecollateStringColumnsProcessor now work on Oracle for columns with content and on MS SQL Server for indexed columns — migrations that failed there before can be retried.

  • Table row-class (#29815): new <table row-class="row -> …"> / <composition-table row-class=…>; with <inputs> the input channel values come first and the row object last. (In alpha12 these scripts lose their lambda head.)


7. Verification checklist

  1. Regenerate wrappers, then mvn clean install (enable tests if possible).
  2. Start the application; read the startup log for configuration errors (access-parent, OpenAPI schemas, unknown MUI part names, <text tone>, detail-size, drop configuration).
  3. Log in, open every React view; try every drag-and-drop interaction (kinds, order, refuse-if).
  4. Call every OpenAPI operation with realistic request bodies (400 = schema mismatch); check that technical users have non-empty passwords in every environment.
  5. Check custom styling visually (tables, trees, dialogs, app shell, panels, cards, split panes, wizard).
  6. Report to the user every skipped step and every user-visible effect (lost personalization of <adaptive-detail> content, changed <on-submit> behavior, visual changes).
  • Get Started
  • Github
  • Discord
  • Das Unternehmen hinter TopLogic
  • Softwareentwicklung heute
  • Kontakt

© Copyright – Business Operation Systems GmbH

  • top-logic.com
  • Nutzungsbedingungen
  • Impressum
  • Rechtlicher Hinweis
  • Datenschutz
  • DE
  • Login