From c54840f8c2aafc20f7b7f4733577d68d03aa8deb Mon Sep 17 00:00:00 2001 From: Kai Moritz Date: Fri, 29 May 2026 19:02:46 +0200 Subject: [PATCH] =?utf8?q?`CLAUDE.md`=20=C3=BCbersetzt=20und=20weitere=20E?= =?utf8?q?rkl=C3=A4rungen=20zu=20den=20Live-Codings=20erg=C3=A4nzt=20(mit?= =?utf8?q?=20Hilfe=20von=20Claude)?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 371 +++++++++++++++++++++++++++++------------------------- 1 file changed, 201 insertions(+), 170 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 4a6eb51c..79117010 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,234 +1,274 @@ # CLAUDE.md -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +Diese Datei enthält Anweisungen für Claude Code (claude.ai/code) beim Arbeiten mit diesem Repository. -## Repository Purpose +## Zweck des Repositories -This is a **Kafka training repository** used for teaching Apache Kafka concepts. It uses a branch-per-exercise model where each exercise lives on its own Git branch. The `scripting` branch (current) contains only management scripts — actual exercise code lives on other branches. +Dies ist ein **Kafka-Schulungsrepository**, das zum Unterrichten von Apache-Kafka-Konzepten verwendet wird. Es nutzt ein Branch-pro-Übung-Modell, bei dem jede Übung auf einem eigenen Git-Branch liegt. Der `scripting`-Branch (aktuell) enthält nur Verwaltungsskripte — der eigentliche Übungscode liegt auf anderen Branches. -## Branch Structure +## Branch-Struktur -Branches follow a naming convention that encodes their role: +Branch-Namen kodieren ihre Rolle durch Suffixe: -| Suffix | Meaning | -|--------|---------| -| *(none)* | Solution / Musterlösung | -| `--vorlage` | Exercise template for students to start from | -| `--livecoding` | Live-coding demo starting point | -| `--livecoding--schritte` | Step-by-step increments of a live-coding session | +| Suffix | Bedeutung | +|--------|-----------| +| *(keiner)* | Lösung / Musterlösung | +| `--vorlage` | Übungsvorlage für Teilnehmer | +| `--livecoding` | Startpunkt für Live-Coding-Demo (Schritt 0) | +| `--livecoding--schritte` | Schrittweise Entwicklung einer Live-Coding-Session | -Branch name prefixes group exercises by topic: -- `grundlagen/*` — Plain Java Kafka client basics -- `producer/*` — Producer-focused exercises (advanced) -- `consumer/*` — Consumer-focused exercises (advanced) -- `springkafka/*` — Spring Kafka API exercises -- `config/*` — Docker/infrastructure configuration examples +Branch-Name-Präfixe gruppieren Übungen nach Thema: +- `grundlagen/*` — Kafka-Grundlagen mit reinem Java-Client +- `producer/*` — Producer-fokussierte Übungen (fortgeschritten) +- `consumer/*` — Consumer-fokussierte Übungen (fortgeschritten) +- `springkafka/*` — Spring-Kafka-API-Übungen +- `config/*` — Docker/Infrastruktur-Konfigurationsbeispiele -Each branch variable in `BRANCHES.sh` has a corresponding `__ROOT` variable that defines its rebase parent, forming a directed dependency chain of exercises. +Jede Branch-Variable in `BRANCHES.sh` hat eine entsprechende `__ROOT`-Variable, die den Rebase-Elternbranch definiert — eine gerichtete Abhängigkeitskette von Übungen. -## Technical Gaps Between The Exercise Groups +## Technische Übergänge zwischen den Übungsgruppen -Common aspects of all exercise groups: +Gemeinsame Aspekte aller Übungsgruppen: -- All exercises have the main focus on the Kafka and Spring Kafka APIs -- Other technologies are used as needed -- If used, other technologies are used to simplify the code and/or setup +- Alle Übungen haben den Fokus auf die Kafka- und Spring-Kafka-APIs +- Andere Technologien werden bei Bedarf eingesetzt +- Werden andere Technologien eingesetzt, dienen sie nur zur Vereinfachung des Codes und/oder Setups -The exercise groups start with simple examples and basic usage. -Later exercise groups introduce more advanced features and use cases. -The order of the exercise groups is: +Die Übungsgruppen beginnen mit einfachen Beispielen und grundlegender Nutzung. +Spätere Übungsgruppen führen fortgeschrittenere Features und Anwendungsfälle ein. +Die Reihenfolge der Übungsgruppen ist: -0. `grundlagen/docker` — Usage of Docker Compose in the exercises, explanations of implied knowledge -1. `grundlagen/*` — Basic usage and simple examples -2. `producer/*` & `consumer/*` — Advanced aspects and usage of the respective Producer and Consumer API -3. `springkafka/*` — Features added by Spring Kafka and usage/integration of the library +0. `grundlagen/docker` — Nutzung von Docker Compose in den Übungen, Erklärungen zu implizitem Wissen +1. `grundlagen/*` — Grundlegende Nutzung und einfache Beispiele +2. `producer/*` & `consumer/*` — Fortgeschrittene Aspekte und Nutzung der Producer- und Consumer-API +3. `springkafka/*` — Features von Spring Kafka und Nutzung/Integration der Bibliothek -The technical gaps between these groups of exercises are bridged by the livecodings, that are maintained in the branches suffixed with `--livecoding--schritte`. -The purpose of these livecodings is: +Die technischen Lücken zwischen diesen Übungsgruppen werden durch Live-Codings überbrückt, die in den Branches mit dem Suffix `--livecoding--schritte` gepflegt werden. +Zweck dieser Live-Codings: -- ... to keep the focus on Kafka and Spring Kafka -- ... to enable the attendees to fully understand the given examples -- ... to enable attendees to follow, even if they are not accustomed with all "off-topic" technologies, that are only used to simplify and support the code and setup of the exercises +- ... den Fokus auf Kafka und Spring Kafka zu behalten +- ... den Teilnehmern ein vollständiges Verständnis der Beispiele zu ermöglichen +- ... den Teilnehmern das Mitverfolgen zu ermöglichen, auch wenn sie nicht mit allen "off-topic"-Technologien vertraut sind, die nur zur Vereinfachung und Unterstützung des Codes und Setups verwendet werden ### `grundlagen/*` -- Contains exercises for consumers and producers -- Uses only the Kafka Consumer/Producer APIs -- Uses only plain Java: no Spring features are used in the implementation -- Needs extra code and setup for technical aspects - - Thread-Handling and parallel execution - - Clean shutdown - - Packaging as a Docker image -- The needed extra code and setup should be as simple as possible, but fully functional +- Enthält Übungen für Consumer und Producer +- Verwendet ausschließlich die Kafka Consumer/Producer APIs +- Verwendet ausschließlich reines Java: keine Spring-Features in der Implementierung +- Benötigt zusätzlichen Code und Setup für technische Aspekte: + - Thread-Handling und parallele Ausführung + - Sauberes Herunterfahren + - Paketierung als Docker-Image +- Der benötigte Zusatz-Code und das Setup sollen so einfach wie möglich, aber vollständig funktionsfähig sein -### `producer/*` and `consumer/*` +### `producer/*` und `consumer/*` -- Contains extended exercises for the Consumer and Producer API of Kafka -- Uses features from Spring Boot to simplify the code and setup -- Spring Kafka is _not_ the topic of these exercises — but it may be already used in included test cases -- Explains Best Practices for the usage of the Producer and Consumer APIs of Kafka +- Enthält erweiterte Übungen zur Consumer- und Producer-API von Kafka +- Verwendet Spring-Boot-Features zur Vereinfachung von Code und Setup +- Spring Kafka ist _kein_ Thema dieser Übungen — kann aber in enthaltenen Testfällen bereits verwendet werden +- Erklärt Best Practices für die Nutzung der Producer- und Consumer-APIs von Kafka ### `springkafka/*` -- Contains extended exercises for Features introduced by Spring Kafka -- Explains Best Practices for Spring Kafka -- Also shows, which features should be used for which use cases -- It is the opinion of the author, Spring Kafka contains very useful features, albeit not all features are meant for common adoption, but were introduced for rather exotic use cases or to enable the implementation of other specialized Spring Libraries +- Enthält erweiterte Übungen für Features von Spring Kafka +- Erklärt Best Practices für Spring Kafka +- Zeigt auch, welche Features für welche Anwendungsfälle geeignet sind +- Nach Meinung des Autors enthält Spring Kafka sehr nützliche Features, wobei nicht alle für den allgemeinen Einsatz gedacht sind — einige wurden für eher exotische Anwendungsfälle oder zur Implementierung anderer spezialisierter Spring-Bibliotheken eingeführt -## Each Exercise Branch +## Jeder Übungs-Branch -A typical exercise branch contains: +Ein typischer Übungs-Branch enthält: -- `README.sh` — the canonical way to run the exercise (builds, starts Docker Compose, runs demo) -- `docker/docker-compose.yml` — local Kafka cluster setup -- `pom.xml` and/or `build.gradle` — Maven/Gradle build (Java 21, Spring Boot 4.0.2) -- `src/` — Java source code (group `de.juplo.kafka`) +- `README.sh` — die kanonische Art, die Übung auszuführen (baut, startet Docker Compose, führt Demo aus) +- `docker/docker-compose.yml` — lokales Kafka-Cluster-Setup +- `pom.xml` und/oder `build.gradle` — Maven/Gradle-Build (Java 21, Spring Boot 4.0.2) +- `src/` — Java-Quellcode (Gruppe `de.juplo.kafka`) -Some branches contain **only** a `docker/docker-compose.yml` with no build files or source. These are infrastructure-only setups for exercises where students experiment further with Kafka clients they have already written in a previous exercise. +Einige Branches enthalten **nur** eine `docker/docker-compose.yml` ohne Build-Dateien oder Quellcode. Dies sind reine Infrastruktur-Setups für Übungen, in denen Teilnehmer mit Kafka-Clients aus einer vorherigen Übung weiterexperimentieren. -Run an exercise: +Übung ausführen: ```bash git checkout -./README.sh # start and demo -./README.sh build # build only -./README.sh cleanup # tear down Docker, clean build artifacts +./README.sh # starten und Demo ausführen +./README.sh build # nur bauen +./README.sh cleanup # Docker beenden, Build-Artefakte bereinigen ``` -### Docker Image Naming in `docker-compose.yml` +### Docker-Image-Benennung in `docker-compose.yml` -The `producer`, `consumer`, or application service in `docker-compose.yml` always references the **exact image that the exercise builds**, using this naming schema: +Der `producer`-, `consumer`- oder Anwendungsservice in `docker-compose.yml` referenziert immer das **exakte Image, das die Übung baut**, nach folgendem Schema: ``` juplo/: ``` -where `` matches `pom.xml`'s `` (Maven) or `settings.gradle`'s `rootProject.name` (Gradle), and `` matches `` / `version`. The current standard version is `1.0-SNAPSHOT`. +wobei `` mit `pom.xml`s `` (Maven) oder `settings.gradle`s `rootProject.name` (Gradle) übereinstimmt und `` mit `` / `version`. Die aktuelle Standardversion ist `1.0-SNAPSHOT`. -**When reviewing or rebasing a branch, always verify** that the image name and version in `docker-compose.yml` match what the build files actually produce. Mismatches are implementation errors and must be flagged and corrected. +**Beim Überprüfen oder Rebasen eines Branches immer verifizieren**, dass der Image-Name und die Version in `docker-compose.yml` mit dem übereinstimmen, was die Build-Dateien tatsächlich erzeugen. Abweichungen sind Implementierungsfehler und müssen gekennzeichnet und korrigiert werden. -## Scripting Branch Scripts +## Skripte im Scripting-Branch -All scripts are only ment to ease the work of a human, by automatic execution of a part of the work. They never work without errors and the human always has to understand the errors, that arise during the rebases and resolve them by hand before re-running the script. +Alle Skripte laden zuerst `BRANCHES.sh`, das die vollständige Branch-Liste und Eltern-Beziehungen definiert. -Never use these scripts and never try to build your own scripts. You may look into the scripts to understand, what has to be done. But first read the following sections, that compact knowledge, that was deduced from the scripts and our discussions in previous sessions. +| Skript | Zweck | +|--------|-------| +| `BRANCHES.sh` | Definiert alle Branch-Namen und ihre `__ROOT`-Eltern | +| `REBASE.sh` | Rebasiert jeden Branch auf seinen `__ROOT`-Eltern | +| `BUILD.sh` | Checkt jeden Branch aus und baut mit Maven + pusht Docker-Image | +| `GRADLE.sh` | Wie BUILD.sh, aber mit Gradle | +| `MAVEN.sh` | `mvn clean install` + `mvn docker:push` für alle Branches | +| `PUSH.sh` | Force-pusht alle Branches zu origin (erstellt vorher zeitgestempelte Backup-Tags) | +| `RESET.sh` | Setzt alle Branches auf `origin/` oder auf ein Tag-Präfix zurück (`./RESET.sh `) | +| `TAG.sh` | Taggt alle Branches als `--` und pusht Tags (`./TAG.sh `) | +| `DIFF.sh` | Diff jedes Branches gegen Remote (oder gegen ein Tag-Suffix, falls angegeben) | +| `COPY.sh` | Kopiert Branches in `../vorlagen`-, `../livecoding`-, `../spickzettel`-Verzeichnisse | +| `patch_gradle_for_si_nexus.sh` | Patcht `build.gradle`/`settings.gradle` für internen Nexus-Mirror | -| Script | Purpose | -|--------|---------| -| `BRANCHES.sh` | Defines all branch names and their `__ROOT` parents | -| `REBASE.sh` | Rebases every branch onto its `__ROOT` parent | -| `BUILD.sh` | Checks out each branch and builds with Maven + pushes Docker image | -| `GRADLE.sh` | Same as BUILD.sh but using Gradle | -| `MAVEN.sh` | `mvn clean install` + `mvn docker:push` for all branches | -| `PUSH.sh` | Force-pushes all branches to origin (creates timestamped backup tags first) | -| `RESET.sh` | Resets all branches to `origin/` or to a tag prefix (`./RESET.sh `) | -| `TAG.sh` | Tags all branches as `--` and pushes tags (`./TAG.sh `) | -| `DIFF.sh` | Diffs every branch against remote (or against a tag suffix if given) | -| `COPY.sh` | Copies branches to `../vorlagen`, `../livecoding`, `../spickzettel` directories | -| `patch_gradle_for_si_nexus.sh` | Patches `build.gradle`/`settings.gradle` to use internal Nexus mirror | +Nach Massenoperationen immer zu `scripting` zurückkehren — Skripte führen am Ende `git checkout scripting` aus. +## Einen neuen Übungs-Branch hinzufügen -## Adding a New Exercise Branch +1. Variablenname und -wert (Branch-Name) in `BRANCHES.sh` eintragen. +2. Entsprechende `__ROOT`-Variable hinzufügen, die auf den Eltern-Branch zeigt. +3. Variablenname in die `BRANCHES`-Liste in `BRANCHES.sh` aufnehmen. +4. `./REBASE.sh` ausführen, um die Konsistenz der Kette zu prüfen. +5. `./PUSH.sh` ausführen, um zu veröffentlichen. -1. Add the variable name and value (branch name) to `BRANCHES.sh`. -2. Add the corresponding `__ROOT` variable pointing to the parent branch. -3. Add the variable name to the `BRANCHES` list inside `BRANCHES.sh`. -4. Run `./REBASE.sh` to verify the chain is consistent. -5. Run `./PUSH.sh` to publish. +## Commit-Konventionen -## Commit Conventions +### Minimale Diffs zwischen verketteten Branches -### Minimal Diffs Between Chained Branches +Beim Einführen von Änderungen in einem Branch wird bewusst darauf geachtet, den Diff gegen den Eltern-Branch so klein wie möglich zu halten. Ziel ist, dass ein Diff zwischen einem späteren Branch und einem seiner Vorfahren **nur zeigt, was der spätere Branch tatsächlich hinzufügt** — kein Rauschen durch unzusammenhängendes Reformatieren oder Umstrukturieren. -When introducing changes in a branch, deliberate care is taken to keep the diff against the parent branch as small as possible. The goal is that a diff between a later branch and one of its ancestors shows **only what the later branch actually adds** — no noise from unrelated reformatting or restructuring. +Dies ist aus zwei Gründen wesentlich: -This is essential for two reasons: +1. **Überblick**: Der Autor kann immer klar sehen, was ein Branch relativ zu seinem Ursprung ändert. +2. **Lehre**: Der Diff wird direkt in Übungen verwendet — z.B. um Teilnehmern genau zu zeigen, welches Boilerplate verschwindet, wenn Spring Boot oder Spring Kafka Features schrittweise aktiviert werden. -1. **Overview**: The author can always clearly see what a branch changes relative to its origin. -2. **Teaching**: The diff is used directly in exercises — for example to show participants exactly which boilerplate disappears when Spring Boot or Spring Kafka features are activated step by step. - -**Implication for rebases**: When an improvement is introduced in an early branch (e.g. removing the `Dockerfile` and obsolete Maven plugins), all downstream branches must adopt this improvement consistently. An `-- ALIGN` commit must **not** re-introduce removed elements. It should contain only the branch-specific changes (e.g. updating `mainClass` from `ExampleProducer` to `ExampleConsumer` in the Jib configuration). +**Implikation für Rebases**: Wird eine Verbesserung in einem frühen Branch eingeführt (z.B. Entfernen des `Dockerfile` und überflüssiger Maven-Plugins), müssen alle Downstream-Branches diese Verbesserung konsistent übernehmen. Ein `-- ALIGN`-Commit darf **keine** entfernten Elemente wieder einführen. Er soll nur die branch-spezifischen Änderungen enthalten (z.B. `mainClass` von `ExampleProducer` auf `ExampleConsumer` aktualisieren in der Jib-Konfiguration). ### MOVE / ALIGN Split -When a class or file is moved to a new branch (or a new spin-off is created from an existing class), the change is always split into exactly two commits: +Wird eine Klasse oder Datei in einen neuen Branch verschoben (oder ein neuer Spin-off aus einer bestehenden Klasse erstellt), wird die Änderung immer in genau zwei Commits aufgeteilt: + +- **`... -- MOVE`** (oder **`... -- ADD`**): kopiert/verschiebt die Datei **vollständig unverändert** — der Inhalt muss 100% identisch mit der Quelle sein. Dies ermöglicht es Git, die Dateihistorie korrekt zu erkennen und zu verfolgen. +- **`... -- ALIGN`**: enthält **alle tatsächlichen Änderungen**, die zur Anpassung der Datei an ihren neuen Kontext nötig sind (z.B. Klasse umbenennen, Main-Klasse in Build-Dateien ändern, Verhalten anpassen). + +**Beim Rebasen** immer prüfen, dass `-- MOVE` / `-- ADD`-Commits keine unbeabsichtigten Änderungen einführen (sie müssen 100%-Kopien bleiben). Verursacht ein Rebase, dass ein `-- MOVE`-Commit Modifikationen enthält, ist dies vor dem Fortfahren zu korrigieren. -- **`... -- MOVE`** (or **`... -- ADD`**): copies/moves the file **completely unchanged** — the content must be 100% identical to the source. This allows git to correctly detect and track file history across branches. -- **`... -- ALIGN`**: contains **all the actual changes** needed to adapt the file for its new context (e.g. renaming the class, changing the main class in build files, adjusting behaviour). +**Beim Auflösen von Konflikten in `-- ALIGN`-Commits**: Die Absicht des ALIGN ist es, gezielte Änderungen auf dem MOVE aufzubauen. Konflikte werden gelöst, indem die beabsichtigten Änderungen des ALIGN (z.B. Klassen-Umbenennung, Build-Datei-Anpassungen) erhalten bleiben, während Inhalte verworfen werden, die durch frühere Verbesserungen obsolet wurden. -**When rebasing**, always verify that `-- MOVE` / `-- ADD` commits do not inadvertently introduce changes (they must remain 100% copies). If a rebase causes a `-- MOVE` commit to include modifications, correct this before continuing. +## Manueller Rebase-Workflow -**When resolving conflicts in `-- ALIGN` commits**, the intent of the ALIGN is to make targeted changes on top of the MOVE. Resolve conflicts by preserving the ALIGN's intended changes (e.g. class renaming, build-file adjustments) while discarding any content that was made obsolete by earlier improvements (e.g. removed Dockerfile-related plugins in pom.xml that no longer apply after the Jib migration). +Das `REBASE.sh`-Skript automatisiert das Rebasen prinzipiell, aber in der Praxis entstehen häufig Konflikte, weil Branches sich absichtlich unterscheiden — sie demonstrieren verschiedene Aspekte von Kafka. Claude Code übernimmt die Rolle des Menschen, der bisher manuell eingreifen musste. -## Manual Rebasing Workflow +### Ansatz zur Konfliktlösung -The `REBASE.sh` script automates rebasing in principle, but in practice conflicts arise frequently because branches intentionally differ — they demonstrate different aspects of Kafka. Claude Code takes over the role of the human who previously had to intervene manually. +**Stillschweigend lösen** (keine Benutzerbestätigung nötig), wenn die Lösung eindeutig ist und direkt aus den Zielen des Übungs-Branches folgt. -### Conflict Resolution Approach +**Innehalten und vorschlagen** bei: +- Einem Konflikt, der auf eine unbeabsichtigte Divergenz hinweist — etwas, das in einem Branch verbessert wurde, aber aus Zeitgründen nie zurückportiert wurde +- Verbesserungen aus späteren Branches (z.B. Testfälle, strukturelle Bereinigungen), die sinnvoll auf frühere Branches angewendet werden könnten +- Gelegenheiten, Branches auf eine Weise auszurichten, die zukünftige Rebase-Konflikte reduziert -**Resolve silently** (no user confirmation needed) when the resolution is straightforward and follows directly from the goals of the exercise branch. +In diesen Fällen: Problem zeigen, erklären warum es wichtig ist, und einen konkreten Vorschlag machen — keine offene Frage stellen. -**Stop and propose** when: -- A conflict hints at an unintentional divergence — something that was improved in one branch but never backported due to time constraints -- Improvements from later branches (e.g. test cases, structural cleanups) could sensibly be applied to earlier branches -- There is an opportunity to align branches in a way that reduces future rebase conflicts +### Allgemeine Prinzipien -In these cases: show the problem, explain why it matters, and make a concrete proposal — don't just ask an open question. +- Branch für Branch in der Reihenfolge arbeiten, wie in `BRANCHES.sh` definiert +- Zwischen **absichtlichen** Unterschieden (verschiedene Lernziele) und **unbeabsichtigten** Unterschieden (Zeitdruck, vergessene Backports) unterscheiden +- Verbesserungen von späteren auf frühere Branches zurückportieren, wo sinnvoll +- Nach dem Rebasen immer zum `scripting`-Branch zurückkehren -### General Principles +## Live-Codings -- Work branch by branch in the order defined in `BRANCHES.sh` -- Distinguish between **intentional** differences (different teaching goals) and **accidental** differences (time pressure, forgotten backports) -- Suggest backporting improvements from later to earlier branches where it makes sense -- After rebasing, always return to the `scripting` branch +Live-Codings verbinden die technischen Lücken zwischen den Übungsgruppen. Jedes Live-Coding zeigt schrittweise die Unterschiede zwischen dem Setup (und den benötigten "off-topic"-Techniken und Boilerplate-Code) in einem gegebenen Ausgangsbranch und einem neuen Zielbranch für die kommenden Übungen. -## Rebase Technical Reference +### Struktur eines Live-Codings -This section documents recurring patterns and decisions established through the Claude-assisted rebase sessions. +**Schritt 0** (`--livecoding`-Branch): Die Anwendung aus dem Ausgangsbranch wird auf die Benennung der Anwendung im Zielbranch umbenannt (mit dem Zusatz `--livecoding`) und das Setup entsprechend vorbereitet. Der Ausgangsbranch ist der ROOT des `--livecoding`-Branches in `BRANCHES.sh`. -### Docker Image Build Tools by Branch Group +**Schritte 1–N** (`--livecoding--schritte`-Branch): Die Anwendung und das Setup werden Schritt für Schritt so umgebaut, dass sie dem Zustand im Zielbranch annähernd entsprechen. Der Zielbranch enthält ggf. noch weitere "off-topic"-Features als "Best Practices", sodass 100% Übereinstimmung weder erwartet noch nötig ist. -| Branch group | Build tool | `pom.xml` | `build.gradle` | +### Übersicht aller Live-Codings + +| `--livecoding`-Branch | Ausgangsbranch (ROOT) | Zielbranch | Übergang | |---|---|---|---| -| `grundlagen/*` | **Jib** (`jib-maven-plugin` 3.4.5) | `` explicit | `jib { container { mainClass = '...' } }` | -| `producer/*`, `consumer/*`, `springkafka/*` | **bootBuildImage** (Cloud Native Buildpacks) | `spring-boot-maven-plugin` + `build-info` goal, `juplo/...` | `bootBuildImage { imageName = "juplo/${project.name}:${project.version}" }` | +| `grundlagen/simple-producer--livecoding` | `grundlagen/simple-producer` | `grundlagen/simple-producer` *(Ausnahme)* | Erklärt Off-Topic-Boilerplate (Clean-Shutdown, Docker-Packaging) | +| `grundlagen/simple-consumer--livecoding` | `grundlagen/simple-consumer` | `grundlagen/simple-consumer` *(Ausnahme)* | Erklärt Off-Topic-Boilerplate (Clean-Shutdown mit `wakeup()`) | +| `consumer/spring-consumer--livecoding` | `grundlagen/simple-consumer` | `consumer/spring-consumer` | Plain Java + Plain Kafka → Spring Boot + Plain Kafka | +| `springkafka/spring-producer--livecoding` | `producer/spring-producer` | `springkafka/spring-producer` | Spring Boot + Plain Kafka → Spring Boot + Spring Kafka (Basis-Muster) | + +**Zum `springkafka/spring-producer`-Live-Coding:** Der Übergang führt nur die grundlegenden Spring-Kafka-Muster ein, die die Spring-Boot-Autokonfiguration erweitern. Fortgeschrittene Features wie `KafkaTemplate` und Listener-Annotationen (`@KafkaListener`) werden in diesem Live-Coding bewusst noch **nicht** eingeführt — diese sind Thema der darauf aufbauenden `springkafka/*`-Übungen. + +**Kein `springkafka/spring-consumer`-Live-Coding:** Es gibt keinen Live-Coding-Branch für den Consumer-Übergang zu Spring Kafka. Der Übergang von `consumer/spring-consumer` zu `springkafka/spring-consumer--kafkalistener` wird direkt durch die `springkafka/*`-Übungen selbst vermittelt. + +### Ausnahme: `grundlagen`-Live-Codings + +Bei diesen beiden Live-Codings ist der Zielbranch **derselbe** wie der Ausgangsbranch — das Muster ist umgekehrt: + +- **Schritt 0** (`--livecoding`-Branch) *entfernt* das Off-Topic-Boilerplate, sodass die Anwendung dem ähnelt, was Teilnehmer auf Basis der entsprechenden `--vorlage` bereits programmiert haben. +- **Schritte 1–N** (`--schritte`-Branch) fügen den Boilerplate-Code Schritt für Schritt wieder hinzu bis zum Zustand des vollständigen Lösungs-Branches. + +### `--livecoding--schritte`-Branches: Besondere Regeln + +Diese Branches repräsentieren schrittweise Übergänge für Live-Coding-Sessions. Ihre Struktur ist pädagogisch wichtig: -The `Dockerfile` is **deleted** on all branches — Jib and bootBuildImage both make it obsolete. +- **Leere Commits nicht überspringen** — jeder Commit ist ein Lehrschritt. Auch wenn der Inhalt eines Schritts nach einem Rebase leer geworden ist, muss der Schritt erhalten bleiben. Innehalten und mit dem Benutzer besprechen, anstatt stillschweigend zu überspringen. +- **Wird der Inhalt eines Schritts durch eine vorgelagerte Verbesserung entfernt**, ist er durch die funktional äquivalente Änderung im neuen Setup zu ersetzen. Beispiel: Der "Docker-Image"-Schritt zeigte ursprünglich ein `Dockerfile` — nach der Jib-Migration zeigt er stattdessen die `mainClass`-Aktualisierung in `pom.xml`/`build.gradle`, weil Jib einen expliziten Einstiegspunkt benötigt, während `bootBuildImage` ihn automatisch erkennt. +- Den Commit-Namen entsprechend umbenennen, sodass er beschreibt, was der Schritt nun demonstriert. +- Das Endergebnis aller Schritte soll dem Zielbranch annähernd (aber nicht zwingend zu 100%) entsprechen. -Image name must always match `juplo/:` (Maven) or `juplo/${project.name}:${project.version}` (Gradle). +## Rebase-Technische-Referenz -### Rebase Strategy by Branch Type +Dieser Abschnitt dokumentiert wiederkehrende Muster und Entscheidungen, die durch die Claude-unterstützten Rebase-Sessions erarbeitet wurden. -All rebases follow the `git checkout -B --claude-N` + `git cherry-pick ` pattern rather than `git rebase`, because conflicts are the norm. Find the unique commits with: +### Docker-Image-Build-Tools nach Branch-Gruppe + +| Branch-Gruppe | Build-Tool | `pom.xml` | `build.gradle` | +|---|---|---|---| +| `grundlagen/*` | **Jib** (`jib-maven-plugin` 3.4.5) | `` explizit | `jib { container { mainClass = '...' } }` | +| `producer/*`, `consumer/*`, `springkafka/*` | **bootBuildImage** (Cloud Native Buildpacks) | `spring-boot-maven-plugin` + `build-info`-Goal, `juplo/...` | `bootBuildImage { imageName = "juplo/${project.name}:${project.version}" }` | + +Das `Dockerfile` ist auf **allen** Branches gelöscht — Jib und bootBuildImage machen es überflüssig. + +Die Dateien `.dockerignore` und `.maven-dockerinclude` sind ebenfalls **obsolet** und sollen aus allen Branches entfernt werden: `.dockerignore` gehörte zum Docker-Daemon-Build-Kontext, `.maven-dockerinclude` zum alten fabric8/bmuschko-Plugin. Beide wurden beim Entfernen des `Dockerfile` übersehen. + +Image-Name muss immer `juplo/:` (Maven) oder `juplo/${project.name}:${project.version}` (Gradle) entsprechen. + +### Rebase-Strategie nach Branch-Typ + +Alle Rebases folgen dem `git checkout -B --claude-N` + `git cherry-pick `-Muster statt `git rebase`, weil Konflikte die Norm sind. Die eindeutigen Commits ermitteln: ```bash git log --oneline --reverse --claude-N ^--claude-N ``` -**Standard solution branches:** +**Standard-Lösungs-Branches:** ```bash git checkout -B --claude-N git cherry-pick ... git tag --claude-N ``` -**`--vorlage` branches** (ROOT = the corresponding solution branch, already rebased): +**`--vorlage`-Branches** (ROOT = der entsprechende Lösungs-Branch, bereits rebasiert): ```bash git checkout -B --claude-N -git cherry-pick +git cherry-pick git tag --claude-N ``` -Vorlage commits typically delete `README.sh`, simplify Java files (removing callbacks), or remove build files for infrastructure-only setups. Accept these deletions — they are intentional. +Vorlage-Commits löschen typischerweise `README.sh`, vereinfachen Java-Dateien (entfernen Callbacks) oder löschen Build-Dateien bei reinen Infrastruktur-Setups. Diese Löschungen sind intentional. -**`--livecoding--schritte` branches:** -Same as vorlage, but cherry-pick all step commits in order. See special rules below. +**`--livecoding--schritte`-Branches:** +Wie Vorlage, aber alle Schritt-Commits in Reihenfolge cherry-picken. Besondere Regeln siehe Abschnitt "Live-Codings". -**Infrastructure-only branches** (no Java source, no build files): -The cherry-pick correctly deletes `pom.xml`, `build.gradle`, `src/` etc. Accept these deletions — they are intentional. +**Reine Infrastruktur-Branches** (kein Java-Quellcode, keine Build-Dateien): +Der Cherry-Pick löscht korrekt `pom.xml`, `build.gradle`, `src/` usw. Diese Löschungen sind intentional. -### Recurring Conflict Patterns +### Wiederkehrende Konfliktmuster -**Version string conflicts** (`pom.xml` / `build.gradle`): -HEAD has `1.1-xxx-SNAPSHOT`, incoming has `1.0-xxx-SNAPSHOT`. Always take incoming. One-liner: +**Versions-String-Konflikte** (`pom.xml` / `build.gradle`): +HEAD hat `1.1-xxx-SNAPSHOT`, eingehender Commit hat `1.0-xxx-SNAPSHOT`. Immer den eingehenden nehmen. Einzeiler: ```bash python3 -c " import re @@ -240,46 +280,37 @@ for fname in ['pom.xml', 'build.gradle']: " ``` -**bootBuildImage migration commit** (e.g., commit `4213dbdf`): -- `pom.xml`: Remove Jib plugin entirely; keep `spring-boot-maven-plugin` with `juplo/...` and `build-info` execution -- `build.gradle`: Replace `jib { ... }` block with `bootBuildImage { imageName = "juplo/${project.name}:${project.version}" }` - -**`Dockerfile` delete/modify conflict:** -Always `git rm Dockerfile` — it is obsolete in all branch groups. - -**Test files deleted in HEAD, modified by incoming commit:** -Restore from the incoming commit: `git checkout -- ` - -**Cherry-pick ordering conflicts** (later comprehensive commit already applied, earlier simpler version conflicts): -When HEAD already contains the more complete version of a file and a subsequent cherry-pick tries to apply an earlier, simpler version — keep HEAD. The earlier commit only added a subset of what HEAD already has. +**bootBuildImage-Migrations-Commit** (z.B. Commit `4213dbdf`): +- `pom.xml`: Jib-Plugin vollständig entfernen; `spring-boot-maven-plugin` mit `juplo/...` und `build-info`-Execution behalten +- `build.gradle`: `jib { ... }`-Block durch `bootBuildImage { imageName = "juplo/${project.name}:${project.version}" }` ersetzen -### `--livecoding--schritte` Branches: Special Rules +**`Dockerfile`-Delete/Modify-Konflikt:** +Immer `git rm Dockerfile` — es ist in allen Branch-Gruppen obsolet. -These branches represent step-by-step transitions for live-coding sessions. Their structure is pedagogically important: +**Testdateien in HEAD gelöscht, durch eingehenden Commit modifiziert:** +Aus dem eingehenden Commit wiederherstellen: `git checkout -- ` -- **Each commit is a teaching step.** -- **If a step's content was removed by an upstream improvement**, replace it with the functionally equivalent change in the new setup. Example: the "Docker Image" step originally showed a `Dockerfile` — after the Jib migration it instead shows the `mainClass` update in `pom.xml`/`build.gradle`, because Jib requires an explicit entry point while `bootBuildImage` auto-detects it. -- Rename the commit message to accurately describe what the step now demonstrates. -- If there is no such change, the commit can be droped, but aske, before! -- The end result of all steps should approximate (but need not be 100% identical to) the solution branch introduced by the live-coding. +**Cherry-Pick-Reihenfolge-Konflikte** (späterer umfassender Commit bereits angewendet, früherer einfacherer Commit konfliktiert): +Wenn HEAD bereits die vollständigere Version einer Datei enthält und ein nachfolgender Cherry-Pick versucht, eine frühere, einfachere Version anzuwenden — HEAD behalten. Der frühere Commit fügte nur einen Teil von dem hinzu, was HEAD bereits hat. -### Library Branches +### Bibliotheks-Branches -When a branch converts the application to a **plain Java library** (not a Spring Boot app, e.g., `sumup-messages--vorlage`), remove all Spring Boot deployment infrastructure from the build files: -- **`pom.xml`**: Remove the `spring-boot-maven-plugin` plugin block -- **`build.gradle`**: Remove `id 'com.gorylenko.gradle-git-properties'` plugin, `springBoot { buildInfo() }` block, and `bootBuildImage { }` block +Wandelt ein Branch die Anwendung in eine **reine Java-Bibliothek** um (keine Spring-Boot-App, z.B. `sumup-messages--vorlage`), ist die gesamte Spring-Boot-Deployment-Infrastruktur aus den Build-Dateien zu entfernen: +- **`pom.xml`**: `spring-boot-maven-plugin`-Plugin-Block entfernen +- **`build.gradle`**: Plugin `id 'com.gorylenko.gradle-git-properties'`, Block `springBoot { buildInfo() }` und Block `bootBuildImage { }` entfernen -### Session Tagging Scheme +### Session-Tagging-Schema -Each rebase session tags every completed branch as `--claude-N`. The tag generation increments per session: -- `--claude-0`: initial automated pass -- `--claude-1`: first manual correction session -- `--claude-2`: most recent session (current) +Jede Rebase-Session taggt jeden abgeschlossenen Branch als `--claude-N`. Die Tag-Nummer erhöht sich pro Session: +- `--claude-0`: erster automatisierter Durchlauf +- `--claude-1`: erste manuelle Korrektursession +- `--claude-2`: letzte abgeschlossene Session +- `--claude-3`: nächste Session (aktuell geplant: `.dockerignore`/`.maven-dockerinclude` entfernen, Schritt-Nummerierung in `consumer/spring-consumer--livecoding--schritte` korrigieren) -Tags serve as restore points. `./RESET.sh claude-2` resets all branches to the `--claude-2` tags. Always tag immediately after completing each branch, before moving to the next. +Tags dienen als Wiederherstellungspunkte. `./RESET.sh claude-2` setzt alle Branches auf die `--claude-2`-Tags zurück. Immer direkt nach Abschluss eines Branches taggen, bevor mit dem nächsten begonnen wird. -## Key Constraints +## Wesentliche Einschränkungen -- `PUSH.sh` force-pushes — it is intentional and expected for this training workflow. -- `--vorlage` branches are skipped by build scripts (they are incomplete by design). -- The `grundlagen/docker` branch is not in `$BRANCHES` but is handled explicitly in several scripts (PUSH, DIFF, RESET, TAG). +- `PUSH.sh` force-pusht — das ist für diesen Schulungsworkflow absichtlich und erwartet. +- `--vorlage`-Branches werden von Build-Skripten übersprungen (sie sind absichtlich unvollständig). +- Der `grundlagen/docker`-Branch ist nicht in `$BRANCHES`, wird aber in mehreren Skripten explizit behandelt (PUSH, DIFF, RESET, TAG). -- 2.39.5