Adventskalender – 2025 –Persistence – Teil 01

Sven Ruppert

Sichtbare Veränderung: Wenn die UI den Speicherzustand zeigt

Mit dem Ende des letzten Adventskalender-Tages war unser URL-Shortener vollständig funktional: Die Admin-Oberfläche konnte Daten filtern, sortieren und seitenweise darstellen – performant, sauber typisiert und vollständig in Core Java implementiert.
Doch hinter dieser Oberfläche lauerte noch ein unsichtbares Problem: Alle Daten existierten nur im Arbeitsspeicher. Sobald der Server neu gestartet wurde, war der gesamte Datenbestand verloren gegangen.

Der Quelltext für diese Version befindet sich auf GitHub unter https://github.com/svenruppert/url-shortener/tree/feature/advent-2025-day-02

Hier ist der Screenshot der Version, die wir nun implementieren werden.

Warum reine In-Memory-Daten an ihre Grenzen stoßen

Diese Volatilität war für frühe Tests akzeptabel, doch mit zunehmender Funktionstiefe zeigten sich klare Grenzen.
In-Memory-Daten haben drei fundamentale Nachteile:

  • Flüchtigkeit: Jeder Neustart setzt den Zustand zurück – ein Verhalten, das in realen Admin-Systemen zu unbrauchbaren Test- und Produktionsdaten führt.
  • Fehlende Historie: Statistische Auswertungen oder Vergleiche zwischen Sessions sind unmöglich, da der Zustand nicht über Zeiträume hinweg persistiert wird.
  • Unsichtbarer Zustand: Der Benutzer sieht im UI nicht, ob er mit einem persistenten oder flüchtigen Speicher arbeitet.

Damit blieb die Anwendung zwar technisch korrekt, aber betrieblich unvollständig. Eine echte Administrationsoberfläche braucht nicht nur Funktionen, sondern auch Verlässlichkeit und Transparenz über den Systemzustand.

Motivation für die Einführung von EclipseStore

An dieser Stelle kommt EclipseStore ins Spiel.
Das Projekt zielt auf einen nahtlosen Übergang von speicherinternen Datenstrukturen zu persistenter Objektgraph-Speicherung – ohne ORM, ohne Datenbank, ohne Bruch in der Architektur.
Damit fügt es sich perfekt in die Philosophie dieses Projekts ein:
Typsicherheit, Einfachheit und vollständige Kontrolle über den Datenfluss.

EclipseStore speichert denselben Objektgraph, den wir bereits im Arbeitsspeicher verwenden, dauerhaft auf dem Datenträger.
Kein Mapping, kein SQL, keine externe Dependency-Injection-Schicht – die Anwendung bleibt pure Java.
Durch die Integration von EclipseStoreUrlMappingStore kann der Shortener damit in zwei Modi laufen:

  • InMemory für schnelle Tests und volatile Sessions,
  • EclipseStore für produktive, persistente Laufzeiten.

Diese Dualität ermöglicht nicht nur echte Betriebsdaten, sondern auch einen sauberen Übergang zwischen Entwicklungs- und Produktionsumgebung – ein wichtiger Aspekt, wenn man Anwendungen systematisch hochrüsten möchte, ohne sie neu zu schreiben.

Ziel: Dauerhafte Speicherung und Live-Status im UI

Doch Persistenz allein war nicht das Ziel dieses Kapitels.
Mindestens ebenso wichtig war, dass der Zustand sichtbar wurde.
Wenn sich der Server im persistenten Modus befindet, soll die Benutzeroberfläche dies unmittelbar anzeigen – am besten in Echtzeit.

Genau hier setzt die neue Status-Anzeige im MainLayout an:
Ein kleines Symbol mit farblichem Feedback (grün, blau, rot) signalisiert, ob das System gerade flüchtig, persistent oder nicht erreichbar ist.
Darunter liegen Mechanismen, die den Serverzustand zyklisch abfragen, Ereignisse verteilen und die UI automatisch aktualisieren, wenn sich der Modus ändert.

Damit verschmelzen Backend und Frontend zu einem gemeinsamen, reaktiven System:
Die Oberfläche wird nicht länger nur zum Fenster auf gespeicherte Daten, sondern zum sichtbaren Spiegel des Systemzustands.
Diese Kopplung von Persistenz und UI-Status bildet das Fundament für alle kommenden Erweiterungen – insbesondere für Sicherheit, Rechteverwaltung und Betriebsdiagnose.

Das neue MainLayout – Kontext und Status in einem Blick

Nachdem wir im vorherigen Kapitel die theoretische Grundlage geschaffen und verstanden haben, warum flüchtige InMemory-Daten nicht ausreichen und wie EclipseStore Persistenz ermöglicht, richtet sich der Blick nun auf die Benutzeroberfläche. Jede Architekturentscheidung wird erst greifbar, wenn sie sich sowohl visuell als auch funktional im UI widerspiegelt.

Der sichtbarste Ausdruck dieser Veränderung findet sich im MainLayout. Mit der Einführung von EclipseStore erhielt es eine neue, subtile, aber äußerst wirkungsvolle Ergänzung: den StoreIndicator. Diese kleine, aber zentrale Komponente befindet sich in der Kopfzeile der Anwendung und zeigt auf einen Blick, ob der Shortener gerade mit einem flüchtigen InMemory-Store oder einem persistenten EclipseStore arbeitet.

Damit verwandelt sich ein zuvor statischer Header in ein dynamisches Steuerzentrum, das nicht nur navigativen, sondern auch informativen Charakter besitzt – ein visuelles Bindeglied zwischen Benutzeroberfläche und Systemzustand.

Architekturgedanke – Sichtbarkeit als Systemfunktion

In der ursprünglichen Vaadin-Oberfläche bestand das Header-Layout lediglich aus einem Titel und der Navigationsstruktur.
Durch die neue Komponente wird dieser Bereich nun erweitert: Zwischen dem Titel „URL Shortener“ und dem Menü erscheint ein Symbol mit Label, das seine Farbe und seinen Text abhängig vom Speicherstatus ändert.

Das Konzept dahinter ist bewusst minimalistisch gehalten:
Statusinformationen sollen nicht über Dialoge oder Meldungen eingeblendet werden, sondern dauerhaft präsent sein – ähnlich einer Statusleiste in professionellen Administrationswerkzeugen.

Technische Integration

Die Integration erfolgte über das bestehende MainLayout, das in Vaadin als zentrales Layout-Template dient. Dort wird beim Aufbau des Headers ein StoreIndicator hinzugefügt:

var adminClient = AdminClientFactory.newInstance();
var storeIndicator = new StoreIndicator(adminClient);
storeIndicator.getStyle().set("margin-left", "auto"); // Rechts ausrichten
HorizontalLayout headerRow = new HorizontalLayout(toggle, appTitle, new Span(), storeIndicator);
headerRow.setWidthFull();
headerRow.setAlignItems(FlexComponent.Alignment.CENTER);

Der StoreIndicator nutzt intern einen AdminClient, der regelmäßig den Server-Endpunkt /store/info abfragt.
Dieser liefert im JSON-Format Informationen über den aktuellen Modus, die Anzahl gespeicherter Mappings und den Zeitpunkt des Serverstarts.

UI-Design und Farbcode

Zur besseren Orientierung wurde ein dreistufiges Farbschema eingeführt:

  • 🟢 EclipseStore aktiv: Dauerhafte Persistenz, Daten werden auf Datenträger geschrieben.
  • 🔵 InMemory-Modus: Flüchtiger Speicher, geeignet für Tests und schnelle Entwicklungszyklen.
  • 🔴 Fehlerzustand: Verbindung nicht erreichbar oder Antwort ungültig.

Dieses Farbsystem ist konsistent mit dem Lumo-Designsystem von Vaadin umgesetzt und sorgt dafür, dass sich die Statusanzeige harmonisch in die UI einfügt.

Wirkung auf das Nutzererlebnis

Der Effekt ist subtil, aber tiefgreifend:
User erkennen sofort, ob sie mit einem persistierenden oder einem temporären System arbeiten. Zugleich entsteht ein stärkeres Vertrauen in die Anwendung, da die Oberfläche nun Transparenz über den Systemzustand bietet – ein Aspekt, der in professionellen Webanwendungen oft vernachlässigt wird.

Im nächsten Kapitel sehen wir uns an, wie der StoreIndicator technisch funktioniert: vom Polling-Mechanismus über die Event-Architektur bis hin zu seiner Selbstaktualisierung im UI.

Live-Status-Komponente: Der StoreIndicator im Detail

Nach der sichtbaren Integration im MainLayout widmen wir uns nun der eigentlichen Funktionsweise des StoreIndicators – der zentralen Komponente, die den Zustand des Systems in Echtzeit anzeigt. Während der Header im UI den Kontext liefert, ist der StoreIndicator das Herzstück, das Datenbewegung sichtbar macht und dem Benutzer unmittelbares Feedback gibt.

Architektur und Zweck

Der StoreIndicator wurde als eigenständige Vaadin-Komponente konzipiert, die das HorizontalLayout erweitert. Sie vereint Logik, Darstellung und Ereignissteuerung in einer klar abgegrenzten Einheit. Ihr Ziel: Den aktuellen Speicherzustand (InMemory, EclipseStore oder Fehlerzustand) regelmäßig abrufen und visuell darstellen.

Dazu nutzt die Komponente periodisches Polling, das den Server-Endpunkt /store/info über einen AdminClient abfragt. Die Antwort enthält Metadaten wie Speicher-Modus, Anzahl der gespeicherten Mappings und den Zeitpunkt des Serverstarts. Auf Basis dieser Daten ändert sich die Anzeige dynamisch.

Lebenszyklus in der Vaadin-UI

Beim Anfügen an die Benutzeroberfläche (onAttach) wird das Polling aktiviert. Das UI ruft in festen Intervallen (alle 10 Sekunden) die aktuelle Systeminformation ab. Beim Entfernen (onDetach) wird diese Hintergrundaktivität wieder beendet – so bleibt die Anwendung ressourcenschonend.

@Override
protected void onAttach(AttachEvent attachEvent) {
    refreshOnce();
    UI ui = attachEvent.getUI();
    ui.setPollInterval(10000); // alle 10 Sekunden
    ui.addPollListener(e -> refreshOnce());
}

Kommunikation mit dem Backend

Die Kommunikation zwischen Frontend und Backend erfolgt über den AdminClient. Dieser ruft den JSON-Endpunkt /store/info auf und wandelt die Antwort in ein StoreInfo-Objekt um:

StoreInfo info = adminClient.getStoreInfo();

boolean persistent = “EclipseStore”.equalsIgnoreCase(info.mode());

Auf dieser Basis werden Farbe, Symbol und Text aktualisiert. Der visuelle Status orientiert sich an drei Zuständen:

  • 🟢 EclipseStore aktiv – persistente Speicherung, Daten liegen auf Datenträgern.
  • 🔵 InMemory-Modus – flüchtige Speicherung, ideal für Tests und Entwicklung.
  • 🔴 Fehlerzustand – Verbindung unterbrochen oder Server nicht erreichbar.

Diese Zustände sind unmittelbar im UI sichtbar und folgen den Farbwerten des Lumo-Themes von Vaadin, was für ein konsistentes Design sorgt.

Ereignisbasierte Aktualisierung

Neben dem Polling setzt der StoreIndicator auf ein ereignisbasiertes Benachrichtigungssystem. Über StoreEvents.publish() sendet er ein globales Event, sobald sich der Speicherstatus ändert. Komponenten wie die OverviewView können dieses Event abonnieren und bei Änderungen automatisch neu laden.

StoreEvents.publish(new StoreConnectionChanged(newMode, info.mappings()));

Dieses lose gekoppelte Eventsystem vermeidet direkte Abhängigkeiten zwischen UI-Komponenten und ermöglicht eine flexible Erweiterbarkeit – ein Muster, das sich auch auf andere UI-Bereiche übertragen lässt.

Der StoreIndicator, der den Zustand des Systems in Echtzeit anzeigt, arbeitet ressourcenschonend und stärkt das Vertrauen der User in die Anwendung.
Durch ihn wird der abstrakte Begriff „Persistenzmodus“ zu einem visuellen Erlebnis – ein perfektes Beispiel dafür, wie Backend-Informationen elegant in die UI integriert werden können.

Cheers Sven

Total
0
Shares
Previous Post

Adventskalender – 2025 – Filter & Search – Teil 02

Next Post

Adventskalender – 2025 –Persistence – Teil 02

Related Posts