Start / Seminare / Quarkus für Spring-Boot-Teams

Modul

Transaktionen, Validierung und Querschnittsfunktionen

4 Kapitel in diesem Modul-Video · Laufzeit

Vertonung mit synthetischer Stimme · Inhalte redaktionell verantwortet · © 2026 HECKER CONSULTING, alle Rechte vorbehalten

Transkript

Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.

Transaktionen und Querschnittliches

0:00 Querschnittliches steht selten im Lastenheft. Niemand schreibt in eine Anforderung, dass der Cache weiterhin funktionieren soll oder dass der nächtliche Lauf genau einmal startet. Es fällt trotzdem sofort auf, wenn es nach einer Migration fehlt — meistens nachts, meistens bei jemandem, der mit der Migration nichts zu tun hatte.

0:18 In diesem Modul sammeln wir deshalb ein, was zwischen den großen Themen liegt: Transaktionen, Aspekte, Validierung außerhalb der REST-Schicht, Caching und Zeitsteuerung.

Transaktionen, Validierung und Querschnittsfunktionen

0:29 Nach der Persistenz das, was sich um sie herum legt. Die Themen wirken klein, sind aber genau die, bei denen eine Migration vom „läuft" zum „läuft wie vorher" kommt. Anschließend widmen wir uns den Tests — dem Werkzeug, mit dem sich dieses „wie vorher" überhaupt nachweisen lässt.

Transaktionsgrenzen und Rollback

0:47 Beginnen wir mit den Transaktionen. Die Annotation sieht fast gleich aus wie in Spring — und genau deshalb lohnt ein zweiter Blick auf das, was dahintersteht. Quarkus benutzt den Jakarta-Standard für Transaktionen; die Implementierung kommt über eine eigene Extension, die Hibernate ohnehin mitbringt. Die Annotation heißt gleich wie in Spring, stammt aber aus einem anderen Paket — achten Sie beim Import darauf, das ist eine beliebte Fehlerquelle.

1:13 Die Varianten kennen Sie: Standardmäßig wird eine bestehende Transaktion übernommen oder eine neue gestartet. Konzeptionell also vertraut. Im Detail unterscheidet sich die Semantik jedoch, besonders bei der Weitergabe und bei der Wiederherstellung nach Fehlern. Sechs Varianten, und die meisten Projekte brauchen zwei davon. Wichtiger als die Liste ist die Fußnote: Ungeprüfte Ausnahmen lösen ein Rollback aus — geprüfte nicht.

1:39 Das ist dasselbe Verhalten, das Sie aus Spring kennen, und dieselbe Falle. Wenn Ihre fachlichen Ausnahmen geprüfte Ausnahmen sind, dann rollt nichts zurück, solange Sie es nicht ausdrücklich sagen. Genau diese Zeile in der Migration zu übersehen, ist leicht — und die Folgen sieht man erst, wenn die Datenbank halbe Vorgänge enthält.

1:59 Zwei Wege auf einer Folie. Oben der deklarative mit einem ausdrücklich gesetzten Zeitlimit — gewöhnen Sie sich das an, gerade bei Läufen, die über Daten iterieren. Unten der programmatische Weg: Manchmal braucht man eine eigene, kurze Transaktion mitten in einem längeren Ablauf, etwa um ein Protokoll zu schreiben, das auch dann erhalten bleiben soll, wenn der Rest zurückrollt.

2:21 Dafür ist diese Form gedacht. Und die Fußnote nennt die globale Voreinstellung, die im Zweifel greift. Der erste Punkt ist der eben besprochene: geprüfte Ausnahme, kein Rollback, keine Warnung. Der zweite ist ein Muster, das man in Migrationen häufig sieht — die Transaktion umschließt einen Aufruf an ein fremdes System und hält damit eine Datenbankverbindung, solange dieses System braucht.

2:44 Der dritte ist eine Ausweichbewegung: Eine neue Transaktion wird gestartet, um ein Sperrproblem zu umgehen, statt es zu verstehen. Und der vierte ist der Kern dieses Moduls: Propagation wird aus Spring übernommen, ohne die Semantik des Standards zu prüfen.

Interceptors statt AOP

2:59 Kommen wir zu dem Thema, bei dem Spring-Teams am ehesten etwas vermissen: aspektorientierte Programmierung — und was hier an ihre Stelle tritt. In CDI läuft Querschnittliches über Interceptors. Sie definieren eine Markierungsannotation, schreiben eine Interceptor-Klasse und setzen die Annotation dorthin, wo sie wirken soll.

3:19 Der Unterschied zu einem Aspekt mit Ausdruck ist entscheidend: Die Zuordnung steht im Code, nicht in einer Ausdruckssprache. Das Bild: Statt einer Regel, die alle Türen im dritten Stock betrifft, kleben Sie ein Schild an jede Tür. Mehr Arbeit beim Aufkleben — dafür sieht jeder, der vor der Tür steht, sofort, was gilt. Die Gegenüberstellung zeigt einen Zielkonflikt, den man ehrlich benennen sollte.

3:43 Ein Ausdruck erfasst mit einer Zeile hundert Stellen — das ist mächtig und genau deshalb schwer zu überblicken. Wer in einem gewachsenen System nachvollziehen will, was bei einem Methodenaufruf alles passiert, kämpft mit genau dieser Mächtigkeit. Die Annotation ist umständlicher und dafür sichtbar. Und wieder entscheidet der Zeitpunkt: Die Zuordnung fällt zur Bauzeit, deshalb gibt es keine dynamische Proxy-Erzeugung.

4:07 Für die Migration heißt das: Ein weiter Pointcut wird zu vielen kleinen Annotationen — und dabei kann etwas durchrutschen. Validierung ist nicht nur ein Thema für Endpunkte. Die Extension prüft auch Methodenparameter von Diensten, wenn Sie sie markieren. Der wichtige Unterschied steht im dritten Punkt: Im Dienst kommt ein Verstoß als Ausnahme an, nicht als hübsche 400er-Antwort.

4:30 Wer das nicht behandelt, lässt eine technische Ausnahme bis zum Endpunkt durchlaufen — und die Antwort, die der Client dann sieht, ist selten die, die man wollte. Und wenn Sie volle Kontrolle brauchen, lässt sich der Prüfer auch direkt injizieren und von Hand aufrufen. Der erste Punkt ist die Kernfrage dieses Kapitels: Ein Ausdruck traf mehr Stellen als gedacht, und die Annotationsvariante deckt weniger ab — prüfen Sie das gezielt, statt es zu hoffen.

4:57 Der zweite ist die unbehandelte Ausnahme aus dem Dienst. Der dritte ist ein Missbrauch, den man häufig sieht: Interceptors, die Fachlogik enthalten und damit Verhalten verstecken. Und der vierte ist technisch: Eine Bean in einem Pseudo-Scope wird nicht abgefangen, weil kein Stellvertreter dazwischenliegt. Das erklärt so manchen Interceptor, der einfach nicht anspringt.

Caching, Scheduling und asynchrone Ausführung

5:19 Drei kleine Themen zum Schluss, die in keiner Migration fehlen — und die im verteilten Betrieb zwei sehr konkrete Fragen aufwerfen. Für Caching gibt es eine eigene Extension mit Annotationen, die sich fast wie ihre Spring-Gegenstücke lesen; darunter arbeitet standardmäßig eine bewährte lokale Cache-Bibliothek. Für Zeitsteuerung gibt es die Scheduler-Extension.

5:40 Merken Sie sich einen Hinweis der Dokumentation: Wer einen geclusterten Scheduler braucht, bei dem eine Aufgabe im Verbund genau einmal läuft, nimmt die Quartz-Extension. Der einfache Scheduler läuft in jeder Instanz — was für viele Aufgaben völlig richtig und für manche fatal ist. Zwei Muster auf einer Folie, und beide sind unspektakulär.

6:00 Wichtig ist die Kleinigkeit im zweiten Block: Der Zeitplan steht nicht als Literal in der Annotation, sondern als Verweis auf einen Konfigurationsschlüssel. Damit lässt sich der Zeitplan je Umgebung ändern, ohne neu zu übersetzen — und in der Testumgebung auch ganz abschalten. Beim Cache oben ist der markierte Parameter der Schlüssel des Eintrags. Wählen Sie hier bewusst, was hineingehört, und lassen Sie alles weg, was sich ändern kann.

6:26 Jetzt zur wichtigsten Folie dieses Moduls. Zwei Mechanismen, die lokal wunderbar funktionieren, verhalten sich im Cluster anders. Der einfache Scheduler läuft in jeder Instanz — drei Pods bedeuten drei Abrechnungsläufe. Die Bordmittel gegen Überschneidungen wirken nur innerhalb eines Prozesses, nicht über Instanzen hinweg.

6:45 Und der lokale Cache ist prozesslokal, jede Instanz hält also ihren eigenen Stand; nach einer Invalidierung wissen die anderen nichts davon. Beides ist kein Mangel, sondern eine bewusste Bauweise. Man muss sie nur kennen, bevor man skaliert. Der erste Punkt ist die praktische Folge der letzten Folie und passiert erstaunlich oft: Nach dem Skalieren startet der nächtliche Lauf dreimal.

7:08 Der zweite ist ein Klassiker jeder Cache-Einführung — der Eintrag wird nie ungültig, weil die Invalidierung am falschen Aufruf hängt. Der dritte ist technisch subtil: Ein veränderliches Objekt als Cache-Schlüssel führt zu Treffern, die keine sind. Und der vierte ist migrationsspezifisch: Cron-Ausdrücke werden aus Spring übernommen, ohne die eingestellte Ausdrucksvariante zu prüfen — und ein Ausdruck, der sich um ein Feld verschiebt, läuft zur falschen Zeit.

Übung

7:34 In der Übung nehmen wir uns den nächtlichen Abrechnungslauf von Pfandkreis vor — und provozieren einen Fehler mittendrin. Das Erfolgskriterium ist hier bewusst als Negativtest formuliert: Bei einem Fehler mitten im Lauf darf die Datenbank keine halben Buchungen enthalten. Und der Hinweis auf der Folie ist der eigentliche Lerninhalt: Lösen Sie zwei verschiedene Fehler aus, eine geprüfte und eine ungeprüfte Ausnahme, und notieren Sie den Unterschied.

8:00 Diese fünf Minuten sind die mit Abstand lohnendste Investition dieses Moduls — sie machen aus einer Folienaussage eine Erfahrung. Erfolgreich sind Sie, wenn der Lauf zeitgesteuert startet, bei einem Fehler sauber zurückrollt und keine halben Buchungen hinterlässt. Halten Sie zusätzlich fest, wie Sie bei mehreren Instanzen doppelte Läufe verhindern würden.

8:20 Der erste Schritt ist eine Denkaufgabe und keine Tippaufgabe: Wo genau liegt die Transaktionsgrenze eines Laufs, der über viele Datensätze geht? Eine große Transaktion ist einfach zu verstehen und sprengt jedes Zeitlimit. Viele kleine sind robuster und brauchen einen Wiederaufsetzpunkt. Beide Antworten sind vertretbar — nur begründet müssen sie sein. Danach folgt das Handwerk mit Cache und Zeitplan, und im letzten Schritt schauen Sie in die Datenbank.

8:47 Nicht ins Log, in die Datenbank. Der erste Punkt ist die typische Antwort auf die Denkaufgabe von eben: alles in eine Transaktion, und das Zeitlimit schlägt zu. Der zweite betrifft Caches generell — das Füllen wird migriert, das Invalidieren vergessen. Der dritte ist die häufigste Lücke in jeder Übung und in jedem Projekt: Es wird nur der Erfolgsfall geprüft.

9:08 Und der vierte ist der, der später am meisten kostet: Die Mehrfachausführung im Cluster bleibt bis zum Produktivgang unentdeckt, weil lokal eben nur eine Instanz läuft.

Lieber mit Trainer? Dieses Modul ist Teil unserer Team-Schulungen — mit Übungen, Ihrem eigenen Code und Fragen, die ein Video nicht beantwortet. Mehr erfahren →