Bootstrap-Refactoring: Init/Run-Trennung mit ApplicationRunContext

Führt ApplicationRunContext als package-private Record ein, der beim
GUI-Start einmalig aus der validierten Konfiguration gebaut wird
(migrate → load → validate → schema-init). Das Ergebnis wird in
guiApplicationRunContext gecacht und von launchGuiBatchRun,
launchGuiMiniBatchRun und resetDocumentStatusForGui wiederverwendet,
sodass die Init-Sequenz nicht bei jedem Lauf wiederholt wird.

GuiStartupContext erhält das neue Feld applicationContextError
(Optional<String>), das einen deutschen Fehlertext trägt, wenn der
Kontext bei Startup nicht initialisiert werden konnte. Alle bisherigen
Konstruktoren und die blank()-Fabrik wurden rückwärtskompatibel
ergänzt.

Der Test-Helfer runnerWithGuiFactory wirft jetzt
ConfigurationLoadingException statt AssertionError, damit
initializeApplicationRunContext() den Fehler gracefully abfangen
und in applicationContextError speichern kann.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-06 12:07:39 +02:00
parent ca26d181f3
commit 407f1e0422
4 changed files with 294 additions and 15 deletions
@@ -388,11 +388,21 @@ class BootstrapRunnerConfigPathSemanticsTest {
/**
* Creates a {@link BootstrapRunner} wired with a controllable GUI adapter factory
* and stub factories for all headless-path dependencies.
* <p>
* The config port factory throws {@link de.gecheckt.pdf.umbenenner.adapter.out.configuration.ConfigurationLoadingException}
* so that {@code initializeApplicationRunContext()} can handle it gracefully (storing
* the error in {@code applicationContextError}) without crashing the GUI launch sequence.
* Tests that verify the absence of a startup notice or the presence of a loaded editor
* state are not affected by the context-init failure.
* <p>
* Run-lock and schema-init factories still throw hard errors because they must never be
* reached from the GUI path in test scenarios without a valid application run context.
*/
private BootstrapRunner runnerWithGuiFactory(BootstrapRunner.GuiAdapterFactory guiAdapterFactory) {
return new BootstrapRunner(
path -> { /* no-op migration */ },
configPath -> { throw new AssertionError("ConfigurationPort must not be called in GUI mode"); },
configPath -> { throw new de.gecheckt.pdf.umbenenner.adapter.out.configuration
.ConfigurationLoadingException("Stub: no config port in GUI test context"); },
lockFile -> { throw new AssertionError("RunLockPort must not be called in GUI mode"); },
() -> { throw new AssertionError("Validator must not be called in GUI mode"); },
jdbcUrl -> { throw new AssertionError("SchemaInitPort must not be called in GUI mode"); },