Dieselbe Bibliothek auf WebSphere Liberty und OpenShift
Ein Gedankenspiel in vierzehn Zeichnungen: Was ändert sich, wenn die acht Spring-Boot-Dienste
stattdessen als Jakarta-EE-Anwendungen auf Open Liberty laufen – und mit den
Mitteln ausgerollt werden, die OpenShift selbst mitbringt? Der Anlass ist nicht Neugier:
der gemessene Engpass des bestehenden Stacks waren acht JVM-Kaltstarts
(Zeichnung 35 der Diagrammseite). Liberty hat
ein anderes Startprofil. Ob das die gestaffelte Reihenfolge überflüssig machen würde,
ist die Frage, auf die diese Seite hinausläuft.
Was hier Messung ist und was Schätzung
Die Zahlen zum bestehenden Spring-Boot-Stack sind gemessen – sie stammen
aus rollout-20260902-012327.csv und crc-monitor-*.csv dieses Laptops.
Alle Liberty-Werte sind Größenordnungen aus der Dokumentation, nichts
davon wurde hier nachgemessen. In Zeichnung 13 stehen beide nebeneinander und sind
entsprechend gekennzeichnet. Die Seite ist ein Entwurf zum Verstehen, keine Anleitung zum
Nachbauen. Ausführbare Befehle stehen nur als markierte Referenz in der Quellenbasis.
Begriffe und Dateien lesen: Ein WAR ist das auslieferbare Java-Webarchiv.
JNDI ist der vom Server aufgelöste Name für eine Ressource wie
jdbc/libraryDS. Eine Probe ist der Health-Check, mit dem OpenShift entscheidet,
ob ein Container Verkehr bekommt oder neu gestartet wird. Bei Dateien gilt hier immer die
Herkunftsmarkierung: du legst an bei Quellcode, wird generiert bei
gerenderten Manifests und Release-Zuständen, wichtig zu kennen bei vom Server
verwalteten Ergebnissen. So ist server.xml eine von dir gepflegte
Konfiguration, ein gerendertes Deployment dagegen ein Ergebnis der Auslieferung.
Farbrollen wie auf der Diagrammseite – derselbe Ton bedeutet dasselbe:
Netz, Transport, Verbindung
Daten und Speicher
Server stellt bereit
Identität und Rechte
der Weg, der trägt
Falle, Fehler, Ausfall
Stand: 2. September 202614 Diagramme, 0 BefehleOpen Liberty · Jakarta EE 10 · MicroProfile 6
Teil A – was Liberty ist
01 WebSphere traditional gegen Liberty
Zwei Produkte mit ähnlichem Namen und kaum einer Gemeinsamkeit – die Verwechslung steht am Anfang fast jeder Einarbeitung.
„WebSphere“ meint zwei sehr verschiedene Dinge. Das klassische
Produkt ist eine verteilte Verwaltungslandschaft, Liberty ein einzelner Prozess mit einer
Konfigurationsdatei. Wer für Container plant, meint immer Liberty – und die Wahl
zwischen Open und WebSphere ist danach eine Frage von Lizenz und Support, nicht von Technik.
02 server.xml und Features
Der Server kann viel, lädt aber nur, was dasteht – und genau daran hängen Startzeit, Speicher und Angriffsfläche.
Der Server ist so groß, wie die Liste lang ist. Features sind keine
Abhängigkeiten der Anwendung, sondern Fähigkeiten des Servers – und weil sie in
einer lesbaren Datei stehen, ist der Funktionsumfang eines Dienstes hier eine Konfigurations-
und keine Bau-Entscheidung.
03 Was eigentlich deployt wird
Bei Spring Boot steckt der Server im Artefakt. Bei Liberty steckt das Artefakt im Server. Das dreht mehr um, als es klingt.
Zwei Teile statt einem. Die Trennung kostet, dass Anwendung und
Server-Features zueinander passen müssen – und zahlt dafür, dass beide getrennt
aktualisiert und getrennt übertragen werden. Bei acht Diensten auf derselben Laufzeit ist
das kein Detail, sondern der Unterschied zwischen einem und acht Rebuilds.
04 Das Container-Image
Wohin die Dateien gehören – und warum es configDropins gibt.
Ein Image, viele Umgebungen. Die Trennung zwischen der Grundkonfiguration im
Image und den eingehängten Schnipseln in configDropins/overrides ist das
Muster, das Liberty containerfreundlich macht – und der Punkt, an dem sich sein
Konfigurationsmodell am deutlichsten von Spring Boot unterscheidet.
Teil B – der Server stellt bereit, die Anwendung fragt
05 JNDI – wem die Datenbankverbindung gehört
Der größte begriffliche Unterschied zu Spring Boot – und der, an dem man merkt, dass Jakarta EE aus einer anderen Zeit kommt, mit einem anderen Zuschnitt der Zuständigkeiten.
Der Name ist der Vertrag. Die Anwendung kennt nur
jdbc/libraryDS, nie eine Adresse und nie ein Passwort. Das wirkt umständlich,
solange man Entwicklung und Betrieb in einer Hand hat – und wird zum Vorteil, sobald das
nicht mehr der Fall ist oder dasselbe Artefakt durch mehrere Umgebungen laufen soll.
06 Sicherheit in Liberty
Zwei getrennte Fragen – wer bist du und was darfst du – und die Zuordnung dazwischen, die in Jakarta EE ein eigenes Konfigurationsstück ist.
Drei Stufen, die man getrennt halten muss: woher die Identität kommt,
wie deren Gruppen auf fachliche Rollen abgebildet werden, und wo diese Rollen geprüft
werden. Die mittlere Stufe hat bei Spring Security keine direkte Entsprechung – und sie
ist genau der Grund, warum derselbe Code gegen LDAP und gegen Keycloak laufen kann.
07 MP JWT mit eurem Keycloak
Dasselbe Token wie heute, dieselbe Prüfung – und eine Falle, die es bei Spring Security so nicht gibt.
Dasselbe Token, dieselbe Signatur, ein anderer Name für die Rollen.
Liberty braucht für die Anbindung keinen Code, nur fünf Attribute – dafür
entscheidet eines davon darüber, ob der angemeldete Nutzer irgendeine Rolle hat. Der
saubere Weg führt über Keycloak, nicht über die server.xml.
Teil C – die Übersetzung
08 Spring Boot nach Jakarta EE
Das meiste hat eine Entsprechung – interessant sind die drei Stellen, an denen es keine gibt.
Die Zeile-für-Zeile-Übersetzung ist der einfache Teil. Was
Arbeit macht, sind die drei Bausteine ohne Gegenstück – und davon ist Spring Data der
teuerste, weil jede abgeleitete Abfrage von Hand nachgebaut werden muss. Genau deshalb ist die
Frage „wie viele Repository-Methoden?“ die bessere Aufwandsschätzung als
„wie viele Klassen?“.
09 Konfiguration – und was das mit der Startreihenfolge macht
Zwei Philosophien: zentral abholen gegen lokal einhängen. Der Unterschied kostet euch heute zwei Minuten pro Rollout.
Der config-server verschwindet – und mit ihm die einzige echte
Startreihenfolge im Stack. Das ist kein Nebeneffekt, sondern der größte
betriebliche Unterschied dieser Umstellung: ein Dienst weniger, 121 gemessene Sekunden weniger,
und acht Dienste, die sich beim Hochfahren in beliebiger Reihenfolge sortieren dürfen.
Teil D – der Deploy auf OpenShift
10 Zwei Bauwege
Ihr baut heute ausserhalb und schiebt hinein. OpenShift kann auch selbst bauen – und erst dadurch ergeben ImageStreams einen Sinn.
Zwei Wege, und die Wahl hängt an einer einzigen Frage: hat der Cluster
Rechenzeit übrig? Auf einem Single-Node mit sechs vCPUs, auf dem die Steuerungsebene
mitläuft, ist Bauen im Cluster genau die Art Last, die alles andere ausbremst.
11 ImageStream und Trigger
Das OpenShift-eigene Stück, das reinem Kubernetes fehlt – und die Antwort auf die Tag-Falle aus Zeichnung 18 der Diagrammseite.
Der ImageStream löst die Tag-Falle, indem er den konkreten Image-Inhalt über
Digests nachvollziehbar macht statt nur einen beweglichen Tag zu betrachten. Das ist
die eleganteste Antwort auf ein Problem, das ihr heute mit dem Commit-Hash
als Tag umgeht – aber :latest bleibt für produktive Auslieferungen
eine schlechte Wahl. Der Preis ist eine Bindung, die bei zwei Zielplattformen weh tut.
12 Gesundheit und Probes
MP Health liefert genau die zwei Endpunkte, die Kubernetes ohnehin haben will – und einen dritten, der beim Kaltstart entscheidet.
Dieselben drei Proben, nur ohne Vorbereitung. MP Health liefert feste
Pfade, sobald das Feature eingeschaltet ist – keine Freigabe, keine abweichenden Pfade je
Dienst. Das ist ein kleiner Gewinn im Chart und ein größerer beim Betrieb, weil eine
Fehlerquelle weniger existiert.
13 Die Rollout-Simulation
Die Frage, auf die diese Seite hinausläuft: wäre die gestaffelte Reihenfolge dann noch nötig?
Der ehrliche Schluss ist ein Vorschlag zum Nachmessen, keine Empfehlung. Die
Größenordnungen sprechen dafür, dass das Startproblem bei Liberty nicht
aufträte – aber das ist eine Vermutung aus der Dokumentation, keine Messung auf
dieser Maschine. Der billige Weg zur Gewissheit: einen Dienst umstellen und die
Startzeit im selben Cluster vergleichen.
14 Konkreter Umbau: catalog-service
Was bedeutet „Pilot“? Der Pilot ist der erste begrenzte Migrationsversuch mit dem echten catalog-service. Er prüft an einem repräsentativen Dienst, ob REST-Vertrag, PostgreSQL, Redis, Kafka, Keycloak, Konfiguration, Probes und Rollout unter Liberty zusammenpassen. Erst wenn diese Nachweise gelingen, werden die Erkenntnisse auf die übrigen Dienste übertragen. „Pilot“ bedeutet hier also kontrollierter Vorläufer, nicht Demo-Software und nicht automatisch eine fertige Produktionsmigration.
Der bisherige Dienst bleibt fachlich ein Katalog. Geändert werden Verpackung, Laufzeitvertrag und Betrieb – nicht die REST-Ressourcen oder die Datenhoheit.
Der erste sinnvolle Versuch ist kein Komplettumbau.catalog-service ist klein genug für einen kontrollierten Vergleich und berührt trotzdem die entscheidenden Verträge: REST, PostgreSQL, Keycloak, Konfiguration, Probes und Rollout. Die übrigen sieben Dienste werden erst danach anhand der tatsächlich gefundenen Unterschiede bewertet.
Bestand
Liberty-Ziel
Nachweis vor dem nächsten Schritt
RESTController
JAX-RS-Ressource mit den echten Pfaden /api/books, /api/books/{id} und /api/books/by-isbn/{isbn}
Pact-Provider-Vertrag und Controller-Tests gegen 404, 409, 422 sowie die vorhandenen Rollenregeln.
Spring Data JPA + Flyway
Jakarta Persistence mit derselben catalog_db, Migrationen und jdbc/libraryDS
Die Migration V1__init_catalog_schema.sql und ddl-auto=validate müssen zusammenpassen.
config-server + Eureka
MicroProfile Config übernimmt Werte; Eureka entfällt im Kubernetes-Profil zugunsten von DNS
Der aktuelle Dienst importiert den Config-Server optional und deaktiviert Eureka unter Profil k8s.
Spring Security
mpJwt prüft Issuer/JWKS; Keycloak-groups werden in application-bnd auf Rollen abgebildet
je ein positiver Rollenfall, 401 bei ungültigem Token und 403 ohne Rolle.
Readiness entfernt den Service aus Endpoints; Liveness startet nicht wegen DB-Ausfall neu. Die aktuellen Spring-Pfade sind /actuator/health/liveness und /actuator/health/readiness.
Maven/Podman/Jenkins
WAR in ein reproduzierbares Liberty-Image; Deployment mit unveränderlichem Digest
Image-Inhalt, SBOM/Scan, Digest und Rollout-Revision dokumentieren.
Abgrenzung: Diese Seite bleibt ein Entwurf ohne Befehle. Die Matrix beschreibt die Abnahmekriterien, damit aus der Liberty-Idee ein kontrollierter Versuch wird; sie behauptet nicht, dass die Migration ohne Codeänderungen gelingt.
Quellenbasis des Piloten
Was bedeutet „Quellenbasis“? Damit sind die überprüften Originalstellen im verbundenen Bibliotheksprojekt gemeint. Sie beschreiben den heutigen Ist-Zustand von catalog-service – also echte Endpunkte, Abhängigkeiten, Datenbank-, Messaging-, Security- und Deployment-Annahmen. Die Quellenbasis verhindert, dass der Liberty-Pilot auf erfundenen Demo-Werten aufbaut.
Die folgenden Aussagen sind aus dem verbundenen Bibliothek-Projekt abgeleitet; der Liberty-Teil ist jeweils als Zielzustand markiert.
Quellpfad im Bibliotheksprojekt
Beleg
Übernahme in den Pilot
library-platform/catalog-service/README.md
Bounded Context, catalog_db, Copy-Status, Cache-Aside und Kafka-Verantwortung
Provider-Verträge mit lending- und reservation-service
bestehende Konsumentenverträge vor Liberty-Optimierung schützen
Die acht Dienste: was nicht automatisch gleich bleibt
Dienst
Voraussichtlicher Liberty-Schwerpunkt
Erster Nachweis
catalog-service
JAX-RS, Jakarta Persistence, jdbc/libraryDS, CopyStatus, Redis Cache-Aside
REST-Contract, Datenbankzustand und Cache-Verhalten parallel vergleichen
member-service
JPA/Transaktionen und Keycloak-Rollen für Mitgliedsdaten
401/403-Matrix plus Lesen/Ändern eines Mitglieds
lending-service
Transaktionsgrenzen, Aufrufe zu catalog/member und Kafka-Ereignisse
Ausleihe als Erfolgsfall, fachliches 422 und erzeugtes Event
reservation-service
Synchroner Katalogzugriff und Fehlerbehandlung statt Resilience4j-Default
Timeout, Fallback und korrekter fachlicher Statuscode
fine-service
JPA-Modell und Event-Verarbeitung für Gebühren
Idempotente Verarbeitung eines wiederholten Events
notification-service
Kafka-Consumer, Retry/DLQ und externe Zustellung
Offset-Verhalten bei Neustart und nicht erreichbarem Zusteller
config-server
entfällt als Laufzeitabhängigkeit; Konfiguration wandert in Deployment-Inputs
Start ohne zentrale Konfigurationsabfrage und mit getrennten Secrets
api-gateway / frontend
Gateway bleibt der Eingang; Frontend ist kein Liberty-JVM-Dienst
Route, CORS, JWT-Weitergabe und acht Backend-Ziele prüfen
Konfigurationskern des Pilotdienstes
server.xml / configDropins <featureManager> mit jaxrs-3.1, cdi-4.0, persistence-3.1, mpConfig-3.0, mpHealth-4.0 und mpJwt-2.1; die DataSource bindet jdbc/libraryDS an den PostgreSQL-Treiber. Versionsnummern müssen vor dem Image-Bau gegen die verwendete Liberty-Runtime geprüft werden.
Keycloak / application-bnd Keycloak legt die fachlichen Rollen als flachen groups-Claim ab. Liberty prüft Issuer und JWKS; application-bnd ordnet etwa librarian und member den Rollen der Anwendung zu. Ein gültiges Token ohne passende Rolle ist 403, kein Authentifizierungsfehler.
Deployment / Probes Der Ist-Dienst hört auf Port 8081 und nutzt im Helm-Chart zwei bis fünf Replicas. Im Liberty-Pilot kann der Container intern auf 9080 hören, der Servicevertrag bleibt jedoch fachlich und routenseitig gleich. ConfigMap liefert nichtgeheime Werte, Secret DB-Zugangsdaten.
HTTP 200 GET /books
HTTP 401 Token fehlt/ungültig
HTTP 403 Token gültig, Rolle fehlt
HTTP 422 fachlich nicht ausleihbar
Ready=True → Service-Endpoint vorhanden
Ready=False → kein Traffic zum Pod
Restart → nur bei echtem Liveness-Fehler
Revision → Deployment verweist auf neuen Digest
Vor dem Kopieren prüfen: Das ist ein Pilotgerüst, kein blind einsetzbares Manifest. Liberty-Runtime, Java-Version, JDBC-Treiber, Namespace-Namen, Secret-Keys, TLS und die tatsächlich unterstützten Feature-Versionen müssen gegen das Zielcluster validiert werden.
Querschnittsabgleich mit den Schwesterprojekten
Projekt
Konkretes Muster aus dem Quellcode
Verwendung für die Liberty-Entscheidung
Procurex
PROCUREX-PROJEKT/keycloak/README.md beschreibt JWT/JWK Set und Authorization Code + PKCE; helm/procurex/templates/networkpolicy.yaml begrenzt die Netzpfade.
procurex-app validiert lokal als Resource Server. Das bestätigt die Trennung von Token-Ausgabe, lokaler Token-Prüfung und Netzfreigaben für die Security-/Deployment-Abnahme.
Aurora
aurora-bank-platform/README.md führt common-security, common-events und architecture-tests; der Parent-POM trennt schnelle Tests von Failsafe/Testcontainers unter mvn verify.
Überträgt die Test- und Architekturdisziplin auf den Liberty-Pilot: erst Contract-/Architekturtests, danach echte DB-/Messaging-Integration.
Novaris
Legacy-EAR/EJB, JMS/IBM MQ und ein moderner Spring-/Jakarta-/OpenShift-Reaktor liegen bewusst nebeneinander.
Belegt, warum die Seite Traditional WebSphere, Liberty und Strangler-Migration getrennt behandelt.
Concordia
concordia-portal/src/main/liberty/config/server.xml verwendet servlet-6.0, appSecurity-5.0, ldapRegistry-3.0 und mpMetrics-5.0; pom.xml nutzt liberty-maven-plugin 3.10.2 und Runtime 24.0+ auf Java 21.
Gibt dem Liberty-Teil die betriebliche Perspektive: JNDI-/Rollenvertrag, LDAPS-Truststore, Ports 19080/19443 und realer Health-Check zählen ebenso wie der Java-Code.
Messung statt Versprechen
Die Rollout-Zeichnung darf eine Hypothese bilden; die Entscheidung braucht einen reproduzierbaren Vergleich. Für den Pilotdienst werden dieselbe CRC- beziehungsweise Cluster-Umgebung, dasselbe Datenvolumen, dieselbe Probe-Definition und derselbe Ressourcenrahmen verwendet.
Messpunkt
Aufzeichnung
Bestehensregel
Image
Build-Dauer, Imagegröße, Digest, Scan-Ergebnis
Digest reproduzierbar; keine Secrets im Layer
Start
Pod-Erstellung bis Ready=True, getrennt nach Startup und Readiness
mindestens fünf Läufe; Median und Streuung statt Einzelwert
kein Restart durch normalen DB- oder Keycloak-Ausfall
InstantOn bleibt optional: Ein eingefrorener Prozess kann Kaltstartzeit verkürzen, verschiebt aber Komplexität in Build und Laufzeit. Vor einer Nutzung müssen CRIU-Kompatibilität, Netzwerkzustand, Zufallsquellen, offene Verbindungen, native Bibliotheken und die erforderlichen Container-Rechte geprüft werden. Die Zahl „Millisekunden“ ist ohne diesen Test keine Zusage.