Bevor wir konfigurieren, optimieren oder parallelisieren, brauchen wir eine gemeinsame Sprache. Spring Batch ist ein Framework mit klaren Domänenobjekten. Wenn du sie sauber trennst, jagst du später keine magischen Bugs mehr. Restartability wird planbar statt zufällig. Einfache Eselsbrücke: Ein Job ist die gesamte Aufgabe (z. B. Nightly Import), ein Step ist ein Verarbeitungsschritt darin (z. B. CSV lesen oder Report erzeugen).
Zielbild
Nach diesem Kapitel kennst du die Kernbegriffe Job, Step, JobInstance, JobExecution, StepExecution, JobRepository und ExecutionContext. Du verstehst, was bei einem Lauf tatsächlich passiert und warum die Metadaten so wichtig sind.
Die Begriffslandkarte
Kernidee in einer Zeile:
Job + JobParameters -> JobInstance -> JobExecution -> StepExecution(s)
Und als kurze Definitionen: Ein Job orchestriert eine Batch-Aufgabe und
besteht aus mindestens einem Step. Ein Step ist ein Verarbeitungsschritt,
chunk-orientiert oder tasklet-basiert. Die JobInstance ist die
fachliche Instanz eines Jobs und wird durch Jobname und identifying
JobParameters definiert, z. B. nightlyImportJob mit
businessDate=2026-01-28. Eine JobExecution ist ein konkreter Lauf
einer JobInstance, mehrere Runs erzeugen mehrere JobExecutions. Eine
StepExecution ist ein konkreter Lauf eines Steps innerhalb einer
JobExecution, etwa: Step 2 lief 3:45 Minuten.
Das JobRepository ist die persistente Metadatenbank für Instanzen, Executions, Status, Zähler und ExecutionContexts. Der ExecutionContext ist ein persistenter Key-Value-State für Restartability.
Ein Chunk-Step verarbeitet Items in Blöcken und committet nach jedem Chunk. Typisch ist das bei Importen und Massenverarbeitung, etwa CSV nach Datenbank. Ein Tasklet-Step führt eine einzelne Aufgabe in einem Lauf aus. Typisch ist das für Dinge wie das Löschen von Staging-Tabellen, das Verschieben von Files oder das Anstoßen eines Reports.
Was passiert bei einem Run?
Ein Jobstart läuft in Spring Batch so ab. Der JobLauncher wird mit Job und JobParameters aufgerufen. Spring Batch prüft, ob für Jobname und identifying JobParameters bereits eine JobInstance existiert. Falls ja, wird eine neue JobExecution angelegt, sofern Restart erlaubt ist. Für jeden Step entsteht eine StepExecution, die persistiert wird. Status, Zähler, Exit-Codes und ExecutionContexts landen im JobRepository.
Wichtig: Die Metadaten sind kein Nebeneffekt, sondern das Fundament für Restartability, Monitoring und Recovery. Spring Batch übernimmt das automatisch, du musst dafür keinen eigenen Code schreiben.
JobInstance vs. JobExecution (die häufigste Verwechslung)
JobInstance ist die identifizierende Klammer. Sie entsteht aus dem
Jobnamen (z. B. nightlyImportJob) und den identifying JobParameters
(z. B. businessDate=2026-01-28).
Wenn du denselben Job mit denselben identifying Parametern erneut startest, entsteht keine neue JobInstance, sondern ein neuer JobExecution auf derselben Instanz. Denkbild: JobInstance = Geschäftsdatum 2026-01-28, JobExecution = 1. Versuch und 2. Versuch.
Konsequenz: Ein Re-Run geht nur als neue JobExecution derselben Instanz. Eine neue Instanz entsteht nur mit anderen identifying Parametern. Idempotenz muss zur Parametrisierung passen.
Identifying vs. non-identifying Parameter
JobParameters können und sollten bewusst klassifiziert werden. Identifying
Parameter bestimmen die JobInstance, etwa businessDate. Non-identifying
Parameter sind reine Laufparameter ohne Instanzwirkung, etwa
triggeredBy=manual. Für Einsteiger heißt das: Ändere identifying Parameter,
wenn du eine neue Instanz willst, ändere non-identifying Parameter, wenn du
nur den Lauf variieren willst.
Das ist entscheidend für Restartability. Ein täglicher Batch sollte nicht für jeden Re-Run eine neue JobInstance erzeugen. Sonst verlierst du die Restart-Semantik und umgehst die eigentliche Fehleranalyse.
JobRepository: Metadaten, die dich retten
Das JobRepository ist die persistente Datenbank für den kompletten Verlauf: Instanzen, Executions, Status, Zähler und ExecutionContexts. Es ist der Grund, warum Spring Batch nach einem Crash wieder an der richtigen Stelle weitermachen kann.
Typische Metadaten sind Start- und Endzeitpunkte inklusive Laufdauer sowie Status und Exit-Codes. Dazu kommen Read/Write/Skip/Commit-Zähler und der persistente ExecutionContext für Job und Step.
Diese Daten sind nicht nur für Restartability wichtig, sondern auch für Monitoring und Audits. Deshalb gilt: JobRepository immer persistent betreiben, auch im Einsteiger-Setup (wir nutzen H2).
ExecutionContext: Restartability in klein
Der ExecutionContext ist ein Key-Value-Speicher, der zwischen Runs
persistiert. Die eingebauten Komponenten (z. B. FlatFileItemReader)
nutzen ihn automatisch, um ihre Position zu speichern, damit ein Job
nach einem Crash fortsetzen kann. In eigenen Readern oder Writern kannst
du den ExecutionContext über das ItemStream-Interface auch selbst
beschreiben, etwa um eine eigene Cursor-Position zu persistieren.
Regeln für einen stabilen ExecutionContext: Halte ihn klein und speichere nur Positionsdaten. Sorge für deterministische Inhalte bei gleichen Inputs. Nutze nur einfache, stabile, serialisierbare Typen. Speichere keine Geheimnisse wie Tokens oder Passwörter.
Status vs. ExitStatus
Spring Batch kennt zwei Ebenen. BatchStatus ist der technische Status wie
STARTED, COMPLETED, FAILED oder STOPPED. ExitStatus beschreibt den
fachlichen Ausgang, etwa COMPLETED_WITH_WARNINGS.
BatchStatus ist für das Framework, ExitStatus für dich und deinen Betrieb. Im Monitoring solltest du beides auswerten.
Beispiel: Unser nächtlicher Import als Job
Im Beispielprojekt besteht der Job aus drei Steps: CSV lesen und validieren, Schreiben in die Datenbank und Report erzeugen.
Jeder Step bekommt eine eigene StepExecution. Das JobRepository hält die Zähler und Laufzeiten pro Step, damit du später z. B. sagen kannst: Step 2 dauert plötzlich doppelt so lange.
Anti-Patterns (früh vermeiden)
Ein Timestamp als identifying Parameter erzeugt jeden Re-Run als neue Instanz und macht Restartability sinnlos. Ein ExecutionContext als Datenspeicher ist für Positionsdaten gedacht, nicht für Payloads. Ein In-memory Repository in Produktion kostet Restart, Audits und Monitoring. Wer ExitStatus ignoriert, lässt fachliche Warnungen im Rauschen verschwinden.
Kurzfazit
Job, Step und Execution sind getrennte Ebenen, das ist Absicht. JobRepository und ExecutionContext sind die Basis für Restartability. Identifying Parameter entscheiden über Re-Run oder neue Instanz.
Im nächsten Teil bauen wir das Setup ohne Boot: DataSource, TransactionManager, JobRepository und JobLauncher, sodass wir einen ersten Job sauber starten können.
Alle Teile der Serie: Serie: Spring Batch