Build-Tools: vom Quellcode zum auslieferbaren Artefakt
https://bildung.social/@oerinformatik/
https://oer-informatik.de/build-tools
Build-Tool, Build-Management, Maven, Gradle, Abhängigkeitsverwaltung, Repository, Lifecycle, Task-Graph, Wrapper, Continuous Integration
tl/dr; (ca. 25 min Lesezeit): Build-Tools wie Maven oder Gradle machen aus Quellcode und Bibliotheken wiederholbar ein auslieferbares Programm: Sie lösen Abhängigkeiten auf, kompilieren, testen, packen und veröffentlichen. Der Artikel zeigt, was dabei von Hand passieren müsste, welche Konzepte alle Build-Tools gemeinsam haben, wie sich das Phasenmodell von Maven vom Task-Graphen von Gradle unterscheidet und wie Build-Tools in einer CI-Pipeline arbeiten [AI-Assisted]. (Zuletzt geändert am 12.11.2026)
Dieser Artikel ist Teil einer Artikelreihe über Build-Tools: Grundlagen der Build-Tools / Das Build-Tool Maven / Das Build-Tool Gradle
Schon fit in diesem Thema? Nutze die Kann-Liste und die Leitfragen unter dem Artikel als Checkliste, ob Du die relevanten Kompetenzen bereits hast.
Als Build-Tool-Grundlagen kann ich nach Durchlesen des Artikels…
… die Aufgaben eines Build-Tools nennen und erklären, warum ein Build wiederholbar sein muss.
… die Stationen eines Builds (Abhängigkeiten auflösen, kompilieren, testen, packen, prüfen, veröffentlichen) in der richtigen Reihenfolge darstellen.
… ein kleines Java-Programm von Hand mit
javac,javaundjarbauen und die Schritte einem Build-Tool zuordnen.… die Begriffe Artefakt, Koordinaten, Abhängigkeit, transitive Abhängigkeit, Scope und Repository erklären.
… das Prinzip „Convention over Configuration“ an der Standard-Ordnerstruktur erläutern.
… den Zweck eines Wrappers (
mvnw,gradlew) erklären.
Darüber hinaus kann ich als Build-Tool-Expertenwissen…
… das Phasenmodell von Maven und den Task-Graphen von Gradle unterscheiden und bewerten.
… die Rolle eines Build-Tools in einer CI-Pipeline beschreiben und einen Build-Ablauf als UML-Aktivitätsdiagramm modellieren.
Die Entwicklungsabteilung der CSB-Rad GmbH hat im September 2026 zwei teure Wochen erlebt: Einmal war der Onlineshop drei Stunden offline, weil das Programm auf einem Laptop mit Java 21 gebaut worden war, der Server aber nur Java 17 kannte. Zwei Wochen später ging eine ungetestete Änderung an der Versandkostenberechnung live, und manche Bestellungen wurden plötzlich versandkostenfrei verschickt. Beide Pannen haben dieselbe Ursache: Das Programm wurde von Hand gebaut, jedes Mal ein bisschen anders, und nichts hat geprüft, ob das Ergebnis wirklich in Ordnung ist.
Genau dafür gibt es Build-Tools (build tools, auch Build-Management-Werkzeuge). Sie beschreiben in einer Konfigurationsdatei, was zu einem Projekt gehört und wie daraus ein auslieferbares Programm entsteht. Jeder Build läuft danach gleich ab, egal ob auf Deinem Rechner, auf dem Rechner einer Kollegin oder auf einem Build-Server.
Was erledigt ein Build-Tool?
Ein Build-Tool übernimmt alle wiederkehrenden Arbeiten zwischen „Code ist geschrieben“ und „Programm läuft bei der Kundschaft“. Das folgende UML-Anwendungsfalldiagramm zeigt die typischen Aufgaben. Auslöser sind Entwickler*innen, die auf ihrem Rechner bauen, oder ein CI-Server, der nach jedem Commit automatisch baut:
Abhängigkeiten auflösen: fremde Bibliotheken (z. B. ein Web-Framework oder ein Test-Framework) in der richtigen Version herunterladen und bereitstellen.
Quellcode kompilieren: aus
.java-Dateien Bytecode (.class-Dateien) erzeugen.Tests ausführen: Unit-Tests, Integrationstests und weitere automatische Prüfungen starten und Berichte erzeugen.
Code statisch prüfen: Stilregeln, typische Fehler oder Sicherheitslücken finden, ohne das Programm auszuführen.
Programmpaket erstellen: die kompilierten Klassen und Ressourcen in ein verteilbares Archiv packen, in Java meist eine JAR-Datei (Java Archive).
Artefakt veröffentlichen: das fertige Paket in ein Repository hochladen, damit andere Projekte oder Server es nutzen können.
Dokumentation erzeugen: API-Dokumentation (Javadoc), Testberichte und Abdeckungsberichte zusammenstellen.
Das Ergebnis eines Builds nennt man Artefakt (artifact): ein Paket mit eindeutigem Namen und eindeutiger Version, z. B. versandkosten-1.0.0.jar.
Ein Build von Hand: Was passiert eigentlich?
Um zu sehen, was ein Build-Tool automatisiert, bauen wir zunächst ein kleines Programm ganz ohne Werkzeug. Die Klasse liegt im Paket example.csbrad.hallo; die Ordner entsprechen dem Paketnamen:
package example.csbrad.hallo;
public class App {
public static void main(String[] args) {
System.out.println("Hallo Welt - gebaut mit Maven!");
}
}Mit dem JDK (hier Java 25) sind drei Schritte nötig: kompilieren, starten, packen. Die Befehle unterscheiden sich in der PowerShell und in der Bash nur bei den Pfadtrennern:
# 1. kompilieren: Bytecode landet im Ordner out
javac -d out src\main\java\example\csbrad\hallo\App.java
# 2. starten: Klassenpfad (-cp) zeigt auf den Ordner mit den .class-Dateien
java -cp out example.csbrad.hallo.App
# 3. packen: JAR mit Startklasse im Manifest erzeugen und starten
jar --create --file hallo.jar --main-class example.csbrad.hallo.App -C out .
java -jar hallo.jarFür eine Klasse ohne Bibliotheken ist das überschaubar. In einem echten Projekt wie dem Versandkosten-Service der CSB-Rad GmbH kommen aber schnell dazu:
Bibliotheken: Ein kleiner REST-Dienst mit Spring Boot braucht über 30 JAR-Dateien, die alle im Klassenpfad stehen müssen, und zwar in zueinander passenden Versionen.
Tests: Die Testklassen müssen mit JUnit im Klassenpfad kompiliert und mit einem Test-Runner gestartet werden; schlägt ein Test fehl, darf kein Paket entstehen.
Reihenfolge: Erst Hauptcode, dann Testcode, dann Tests, dann packen. Wer einen Schritt vergisst, liefert veraltete Klassen aus.
Umgebung: Welches JDK wird benutzt? Mit welchem
--release-Wert? Genau daran ist der Shop der CSB-Rad GmbH gescheitert.
Ein Build-Tool schreibt all das einmal in eine Konfigurationsdatei und führt es danach mit einem einzigen Befehl immer gleich aus.
Die Stationen eines Builds
Unabhängig vom Werkzeug läuft ein Build in ähnlichen Stationen ab. Das folgende UML-Aktivitätsdiagramm zeigt einen vereinfachten Ablauf. Schlägt ein Test fehl, wird der Build abgebrochen, es entsteht also kein Paket:
Wichtig ist das Prinzip „schnell scheitern“ (fail fast): Billige Prüfungen (Stilregeln, Versionsprüfungen, Unit-Tests) laufen früh, teure Prüfungen (Integrationstests, Abdeckungsanalyse) später. Sobald eine Station scheitert, bricht der Build ab, und Du bekommst die Fehlermeldung, bevor etwas Kaputtes ausgeliefert wird.
Kernkonzepte, die alle Build-Tools teilen
Convention over Configuration: Die Standard-Ordnerstruktur
Maven hat eine Ordnerstruktur eingeführt, die heute auch Gradle und viele Entwicklungsumgebungen erwarten. Wer sich an diese Konvention hält, muss fast nichts konfigurieren (Convention over Configuration). Nur Abweichungen werden in der Konfigurationsdatei beschrieben:
projekt/
├── pom.xml bzw. build.gradle.kts Konfiguration des Builds
├── src/
│ ├── main/
│ │ ├── java/ Quellcode der Anwendung
│ │ └── resources/ Konfigurationsdateien, Texte, Bilder
│ └── test/
│ ├── java/ Quellcode der Tests (gleiche Pakete)
│ └── resources/ Testdaten
└── target/ bzw. build/ Ausgaben des Builds (nie ins Git-Repository!)
Haupt- und Testcode liegen in zwei spiegelbildlichen Bäumen. Eine Testklasse VersandkostenRechnerTest liegt im selben Paket wie die getestete Klasse VersandkostenRechner, aber unter src/test/java. So darf der Test auch paketsichtbare Elemente nutzen, und trotzdem landet der Testcode nicht im ausgelieferten Paket.
Deklarativ statt imperativ
Ein Shell-Skript wie oben beschreibt imperativ, wie gebaut wird: Befehl für Befehl. Build-Tools arbeiten überwiegend deklarativ: Du beschreibst, was das Projekt ist (Name, Version, Java-Version, Abhängigkeiten, gewünschte Prüfungen), und das Build-Tool weiß, welche Schritte dafür nötig sind. Maven ist dabei sehr streng deklarativ (XML-Datei pom.xml). Gradle erlaubt in seinem Build-Skript (build.gradle.kts, geschrieben in Kotlin) zusätzlich eigene Logik. Das ist mächtiger, aber auch fehleranfälliger.
Koordinaten und Abhängigkeiten
Jedes Artefakt wird über drei Koordinaten (coordinates) eindeutig benannt, ähnlich wie eine Postanschrift:
| Koordinate | Bedeutung | Beispiel |
|---|---|---|
groupId (Gradle: group) |
Organisation oder Projektgruppe, meist umgekehrter Domainname | org.springframework.boot |
artifactId (Gradle: name) |
Name des Artefakts | spring-boot-starter-webmvc |
version |
Version, oft nach Semantic Versioning; -SNAPSHOT kennzeichnet einen Entwicklungsstand |
4.1.2 |
In Kurzform schreibt man org.springframework.boot:spring-boot-starter-webmvc:4.1.2. Für die Beispielprojekte der CSB-Rad GmbH nutzen wir die Gruppe example.csbrad, abgeleitet von der (erfundenen) Domain csb-rad.example.
Ein Projekt deklariert nur seine direkten Abhängigkeiten (dependencies). Diese bringen ihrerseits Abhängigkeiten mit, die das Build-Tool automatisch mitlädt: die transitiven Abhängigkeiten. Der Versandkosten-Service deklariert nur eine einzige Laufzeitbibliothek; das Build-Tool löst daraus über 30 JAR-Dateien auf (Webserver Tomcat, JSON-Bibliothek Jackson, Logging …).
Ein Scope (Gültigkeitsbereich) legt fest, wofür eine Abhängigkeit gebraucht wird:
| Zweck | Maven-Scope | Gradle-Konfiguration |
|---|---|---|
| zum Kompilieren und zur Laufzeit | compile (Vorgabe) |
implementation |
| nur für die Tests | test |
testImplementation |
| nur zur Laufzeit, nicht zum Kompilieren | runtime |
runtimeOnly |
| stellt die Laufzeitumgebung bereit (z. B. Applikationsserver) | provided |
compileOnly |
So landet z. B. JUnit nie im ausgelieferten Programm.
Repositories: Woher kommen die Bibliotheken?
Artefakte liegen in Repositories (Ablagen). Das wichtigste öffentliche Repository ist Maven Central (https://repo.maven.apache.org/maven2/); Maven und Gradle nutzen es gleichermaßen. Auf Deinem Rechner gibt es außerdem ein lokales Repository als Zwischenspeicher (Maven: ~/.m2/repository, Gradle: ~/.gradle/caches). Firmen betreiben oft ein eigenes Repository, in dem sie ihre internen Bibliotheken ablegen und Maven Central spiegeln.
Das folgende UML-Sequenzdiagramm zeigt vereinfacht, wie ein Build-Tool eine Abhängigkeit auflöst: Es sucht zuerst lokal, lädt nur Fehlendes aus dem entfernten Repository und speichert es für den nächsten Build. Danach geht es mit den transitiven Abhängigkeiten aus der pom-Datei des Artefakts genauso weiter:
Deshalb dauert der erste Build eines Projekts oft lange, und deshalb brauchst Du beim ersten Build Internetzugang (bzw. einen korrekt eingetragenen Proxy).
Der Wrapper: Gleiche Werkzeugversion für alle
Selbst wenn die Konfiguration im Git-Repository liegt, bauen zwei Rechner unterschiedlich, wenn dort verschiedene Versionen von Maven oder Gradle installiert sind. Abhilfe schafft ein Wrapper: ein kleines Skript im Projekt (mvnw/mvnw.cmd bzw. gradlew/gradlew.bat) plus eine Eigenschaftsdatei, in der die gewünschte Werkzeugversion steht. Beim ersten Aufruf lädt der Wrapper genau diese Version herunter. Danach rufst Du statt mvn bzw. gradle immer den Wrapper auf. Die Wrapper-Dateien werden mit ins Git-Repository eingecheckt, die Ordner target/ bzw. build/ dagegen nie.
Phasen oder Task-Graph?
Maven und Gradle unterscheiden sich vor allem darin, wie sie die Schritte eines Builds ordnen.
Maven kennt einen festen Lebenszyklus (lifecycle) aus aufeinanderfolgenden Phasen (phases). Rufst Du eine Phase auf, laufen alle Phasen davor mit. mvn package führt also validate, compile und test aus, bevor gepackt wird. Plugins hängen ihre Arbeitsschritte (goals) an einzelne Phasen an:
Gradle dagegen kennt Tasks (Aufgaben), die voneinander abhängen. Aus diesen Abhängigkeiten berechnet Gradle bei jedem Aufruf einen gerichteten, kreisfreien Graphen (directed acyclic graph, DAG) und führt nur die Tasks aus, die für das Ziel nötig sind. gradlew build braucht jar und test, beide brauchen classes, und classes braucht compileJava. Wie sie untereinander angeordnet sind, ist nicht festgelegt. Das UML-Aktivitätsdiagramm zeigt das mit einer Gabelung:
Zwei Eigenschaften des Task-Graphen sparen viel Zeit:
Inkrementelle Builds: Gradle merkt sich Ein- und Ausgaben jedes Tasks. Hat sich nichts geändert, wird der Task übersprungen (
UP-TO-DATE).Build-Cache: Ergebnisse können sogar zwischen Rechnern geteilt werden.
Maven baut dagegen bei jedem Aufruf die Phasen der Reihe nach ab. Dafür ist sein Modell sehr leicht zu verstehen und in jedem Maven-Projekt gleich.
Eine Landkarte der Build-Tools
Build-Tools gibt es für fast jede Sprache. Die Konzepte von oben (Koordinaten, Repositories, Lifecycle oder Task-Graph) findest Du überall wieder:
| Werkzeug | Sprache / Plattform | Konfiguration | Stil | Repository |
|---|---|---|---|---|
| Make | C, C++, allgemein | Makefile |
imperativ, Regeln mit Abhängigkeiten | keines |
| Apache Ant | Java (historisch) | build.xml |
imperativ (Targets) | keines (später Ivy) |
| Apache Maven | Java, JVM | pom.xml |
deklarativ, feste Phasen | Maven Central |
| Gradle | Java, Kotlin, Android | build.gradle.kts |
deklarativ mit Skript, Task-Graph | Maven Central, Gradle Plugin Portal |
| npm | JavaScript, TypeScript | package.json |
Skripte und Abhängigkeiten | npm Registry |
| pip, Poetry | Python | pyproject.toml |
Abhängigkeiten, Build-Backends | PyPI |
| dotnet CLI, MSBuild | C#, .NET | *.csproj |
deklarativ (XML), Targets | NuGet |
| Cargo | Rust | Cargo.toml |
deklarativ | crates.io |
Maven und Gradle im direkten Vergleich
Im Java-Umfeld sind Maven und Gradle die beiden großen Build-Tools. Für das Hello-World-Programm von oben sieht die vollständige Konfiguration so aus. Beide erzeugen ein ausführbares JAR mit Java 25 und brauchen keine einzige Bibliothek:
Datei build.gradle.kts (Kotlin DSL) plus eine Zeile in settings.gradle.kts (rootProject.name = "hallo-gradle"):
plugins {
application
}
group = "example.csbrad"
version = "1.0.0-SNAPSHOT"
java {
toolchain {
languageVersion = JavaLanguageVersion.of(25)
}
}
application {
mainClass = "example.csbrad.hallo.App"
}
tasks.jar {
manifest {
attributes("Main-Class" to application.mainClass)
}
}Bauen und starten: gradlew build und java -jar build/libs/hallo-gradle-1.0.0-SNAPSHOT.jar (oder direkt gradlew run)
Die wichtigsten Befehle im Vergleich (mit Wrapper: mvnw statt mvn, gradlew statt gradle):
| Aufgabe | Maven | Gradle |
|---|---|---|
| kompilieren | mvn compile |
gradlew classes |
| Tests ausführen | mvn test |
gradlew test |
| Paket erstellen (mit Tests) | mvn package |
gradlew build |
| alle Prüfungen inkl. Integrationstests | mvn verify |
gradlew check |
| ins lokale Repository installieren | mvn install |
gradlew publishToMavenLocal |
| Ausgaben löschen | mvn clean |
gradlew clean |
| Abhängigkeitsbaum anzeigen | mvn dependency:tree |
gradlew dependencies |
| Ausgabeordner | target/ |
build/ |
Welches Werkzeug ist besser? Beide sind ausgereift. Maven punktet mit seiner Einheitlichkeit: Wer ein Maven-Projekt kennt, kennt alle. Gradle ist schneller (inkrementelle Builds, Cache) und flexibler, verlangt aber mehr Disziplin, damit Build-Skripte nicht zu kleinen Programmen wuchern. Android-Projekte nutzen Gradle, viele Unternehmensanwendungen Maven. In der Praxis übernimmst Du meist das Werkzeug, das im Projekt schon verwendet wird.
Build-Tools in der CI-Pipeline
Ihren vollen Nutzen entfalten Build-Tools in einer CI-Pipeline (Continuous Integration): Nach jedem git push startet ein Build-Server automatisch denselben Build, den Du auch lokal ausführst. Erst wenn alle Prüfungen bestanden sind, wird das Artefakt veröffentlicht. Die CSB-Rad GmbH plant genau das auf ihrem GitLab-Server:
Damit das klappt, muss der Build ohne Benutzereingaben laufen (Maven: Option -B für batch mode), mit dem Wrapper immer dieselbe Werkzeugversion nutzen und bei einem Fehler mit einem Rückgabewert ungleich 0 enden. Den Rückgabewert setzen Maven und Gradle von selbst. Wie die Prüfungen konkret in den Build eingehängt werden, zeigen die beiden Folgeartikel zu Maven und Gradle am Beispiel des Versandkosten-Service.
Übungsaufgaben
Die Aufgaben spielen bei der CSB-Rad GmbH. Die Beispielprojekte liegen im Repository zu dieser Artikelreihe.
Aufgabe 1.1: Fachbegriffe rund um den Build (Basiskompetenz)
Ordne jedem Begriff eine kurze Erklärung zu (ein Satz genügt). (6 Punkte)
| Begriff | Erklärung |
|---|---|
| Artefakt | |
| Koordinaten | |
| transitive Abhängigkeit | |
| lokales Repository | |
| Wrapper | |
| Convention over Configuration |
| Begriff | Erklärung |
|---|---|
| Artefakt | Ergebnis eines Builds mit eindeutigem Namen und eindeutiger Version, z. B. eine JAR-Datei. |
| Koordinaten | groupId, artifactId und version, die ein Artefakt in einem Repository eindeutig bezeichnen. |
| transitive Abhängigkeit | Abhängigkeit einer Abhängigkeit; sie wird nicht deklariert, sondern vom Build-Tool automatisch mitgeladen. |
| lokales Repository | Zwischenspeicher auf dem eigenen Rechner (z. B. ~/.m2/repository), damit Bibliotheken nur einmal heruntergeladen werden. |
| Wrapper | Skript im Projekt (mvnw, gradlew), das eine festgelegte Version des Build-Tools lädt und benutzt. |
| Convention over Configuration | Wer sich an Standards (z. B. Ordnerstruktur src/main/java) hält, muss nichts konfigurieren; nur Abweichungen werden beschrieben. |
Je Zeile 1 Punkt.
Aufgabe 2.1: Einen Abhängigkeitsbaum lesen (Kernkompetenz)
Eine Auszubildende der CSB-Rad GmbH hat für den Versandkosten-Service mvn dependency:tree ausgeführt. Hier ein gekürzter Ausschnitt der Ausgabe:
example.csbrad:versandkosten-maven:jar:1.0.0-SNAPSHOT
+- org.springframework.boot:spring-boot-starter-webmvc:jar:4.1.2:compile
| +- org.springframework.boot:spring-boot-starter:jar:4.1.2:compile
| | +- org.springframework.boot:spring-boot-starter-logging:jar:4.1.2:compile
| | | \- ch.qos.logback:logback-classic:jar:1.5.38:compile
| | \- org.yaml:snakeyaml:jar:2.6:compile
| +- org.springframework.boot:spring-boot-starter-tomcat:jar:4.1.2:compile
| | ...
| \- org.springframework.boot:spring-boot-webmvc:jar:4.1.2:compile
\- org.springframework.boot:spring-boot-starter-webmvc-test:jar:4.1.2:test
...
Nenne die Koordinaten des Projekts selbst (Gruppe, Name, Version) und erkläre, was
SNAPSHOTbedeutet. (2 Punkte)Welche Abhängigkeiten hat die Auszubildende in ihrer Konfiguration selbst eingetragen? Woran erkennst Du das? (2 Punkte)
Ist
logback-classiceine direkte oder eine transitive Abhängigkeit? Begründe. (2 Punkte)Erkläre, was das letzte Wort
compilebzw.testin jeder Zeile bedeutet und welche Folgetestfür das ausgelieferte Programm hat. (2 Punkte)
Gruppe
example.csbrad, Nameversandkosten-maven, Version1.0.0-SNAPSHOT.SNAPSHOTkennzeichnet einen Entwicklungsstand, der sich noch ändern kann; erst ein Release bekommt eine feste Versionsnummer ohne diesen Zusatz.spring-boot-starter-webmvcundspring-boot-starter-webmvc-test: Sie hängen direkt unter dem Projekt (erste Einrückungsebene,+-bzw.\-ganz links).Transitiv:
logback-classicsteht auf der vierten Ebene des Baums. Es hängt unterspring-boot-starter-logging, das wiederum überspring-boot-startervomspring-boot-starter-webmvcmitgebracht wird. Eingetragen hat es niemand.Es ist der Scope.
compile: wird zum Kompilieren und zur Laufzeit gebraucht und landet im Programm.test: wird nur zum Kompilieren und Ausführen der Tests gebraucht; diese Bibliotheken (JUnit, Mockito …) kommen nicht ins ausgelieferte JAR.
Aufgabe 2.2: Vom Shell-Skript zum Build-Tool (Kernkompetenz)
Bisher baut Cem Sarıkaya das Shop-Backend der CSB-Rad GmbH alle zwei Wochen mit einem selbst geschriebenen Skript auf seinem Laptop:
javac -d out -cp "lib\*" (Get-ChildItem -Recurse src\*.java).FullName
jar --create --file shop.jar --main-class example.csbrad.shop.ShopApp -C out .
scp shop.jar deploy@shop.csb-rad.example:/opt/shop/Ordne jede Zeile einer Station eines Builds zu. Welche Stationen fehlen ganz? (4 Punkte)
Nenne zwei Risiken dieses Vorgehens, die mit einem Build-Tool und Wrapper vermieden werden, und erkläre jeweils kurz, wie. (4 Punkte)
Zeile 1: Quellcode kompilieren (die Bibliotheken liegen von Hand im Ordner
lib). Zeile 2: Programmpaket erstellen. Zeile 3: Artefakt veröffentlichen bzw. ausliefern. Es fehlen: Abhängigkeiten auflösen (Versionen werden nicht verwaltet), Tests ausführen, Paket prüfen (z. B. Integrationstests, Abdeckung, Stilprüfung).Mögliche Antworten (je 2 Punkte):
Falsche Java-Version: Das Skript nutzt das JDK, das gerade auf dem Laptop installiert ist. Mit Build-Tool wird die Ziel-Version festgelegt (
maven.compiler.releasebzw. Toolchain) und z. B. mit dem Enforcer-Plugin geprüft.Ungetestete Auslieferung: Nichts verhindert, dass fehlerhafter Code ausgeliefert wird. Im Build-Tool laufen die Tests vor dem Packen; schlägt einer fehl, entsteht kein Paket.
Unklare Bibliotheksversionen: Die JARs im Ordner
libsind nicht nachvollziehbar. Das Build-Tool lädt deklarierte Versionen inklusive transitiver Abhängigkeiten aus einem Repository.Abhängigkeit von einer Person und einem Rechner: Mit Konfiguration und Wrapper im Git-Repository kann jede Person und jeder CI-Server identisch bauen.
Aufgabe 3.1: Eine Build-Pipeline modellieren (Profilkompetenz)
Sophie Bertram möchte, dass neue Versionen des Shops der CSB-Rad GmbH künftig automatisch gebaut werden. Cem Sarıkaya beschreibt den gewünschten Ablauf:
„Zuerst lädt der Build-Server die Bibliotheken und prüft, ob Java- und Werkzeugversion stimmen. Passen sie nicht, bricht er sofort ab und benachrichtigt das Team. Sonst wird kompiliert, dann laufen die Unit-Tests. Gleichzeitig mit den Unit-Tests darf die Stilprüfung laufen. Wenn beides fertig ist und alles bestanden hat, wird das JAR gebaut und mit den Integrationstests geprüft. Erst wenn auch die bestanden sind, landet das JAR im Firmen-Repository. Bei jedem Fehlschlag wird das Team benachrichtigt.“
Modelliere den Ablauf als UML-Aktivitätsdiagramm. Achte auf Start- und Endknoten, Verzweigungen mit Bedingungen und Zusammenführungen sowie Gabelung und Vereinigung. (10 Punkte)
Bewertungshinweise: Start- und Endknoten (1 Punkt), Aktionen als Tätigkeiten benannt (2 Punkte), drei Verzweigungen mit disjunkten Bedingungen in eckigen Klammern (3 Punkte), Gabelung und Vereinigung für Unit-Tests und Stilprüfung (2 Punkte), jede Verzweigung über eine Merge-Raute zusammengeführt (2 Punkte). Andere Anordnungen sind ebenfalls richtig, solange der Ablauf derselbe bleibt. Statt dreimal „Team benachrichtigen“ kannst Du die Fehlerzweige auch über eine Merge-Raute zu einer gemeinsamen Aktion führen.
Leitfragen
- Welche Aufgaben übernimmt ein Build-Tool?
Es löst Abhängigkeiten auf, kompiliert, führt Tests und statische Prüfungen aus, erstellt Pakete, veröffentlicht Artefakte und erzeugt Dokumentation, und zwar bei jedem Aufruf gleich. siehe Abschnitt „Was erledigt ein Build-Tool?“
- In welcher Reihenfolge laufen die Stationen eines Builds ab, und warum laufen billige Prüfungen zuerst?
Abhängigkeiten auflösen, kompilieren, testen, packen, prüfen, veröffentlichen. Nach dem Prinzip „schnell scheitern“ laufen schnelle Prüfungen früh, damit Du Fehler bekommst, bevor teure Schritte laufen oder Kaputtes ausgeliefert wird. siehe Abschnitt „Die Stationen eines Builds“
- Was unterscheidet eine direkte von einer transitiven Abhängigkeit, und wozu dient ein Scope?
Direkte Abhängigkeiten trägst Du selbst in die Konfiguration ein; transitive bringen diese mit, und das Build-Tool lädt sie automatisch. Der Scope legt fest, wofür eine Abhängigkeit gebraucht wird, z. B. test nur für Tests. siehe Abschnitt „Koordinaten und Abhängigkeiten“
- Woher bekommt ein Build-Tool die Bibliotheken?
Aus Repositories: zuerst aus dem lokalen Repository auf Deinem Rechner, sonst aus einem entfernten Repository wie Maven Central; Heruntergeladenes wird lokal zwischengespeichert. siehe Abschnitt „Repositories: Woher kommen die Bibliotheken?“
- Was bedeutet „Convention over Configuration“, und wozu dient ein Wrapper?
Wer Standards wie die Ordnerstruktur src/main/java einhält, muss nichts konfigurieren. Der Wrapper (mvnw, gradlew) sorgt dafür, dass alle mit derselben Werkzeugversion bauen. siehe Abschnitt „Kernkonzepte, die alle Build-Tools teilen“
- Wie unterscheiden sich das Phasenmodell von Maven und der Task-Graph von Gradle?
Maven führt feste Phasen der Reihe nach aus, beim Aufruf einer Phase alle vorherigen mit. Gradle berechnet aus den Abhängigkeiten der Tasks einen Graphen, führt nur Nötiges aus und überspringt unveränderte Tasks. siehe Abschnitt „Phasen oder Task-Graph?“
- Welche Rolle spielt ein Build-Tool in einer CI-Pipeline?
Der CI-Server ruft nach jedem Push denselben Build auf wie Du lokal; nur wenn alle Prüfungen bestanden sind, wird das Artefakt veröffentlicht. siehe Abschnitt „Build-Tools in der CI-Pipeline“
Links und weitere Informationen
für den Einstieg: Maven in 5 Minutes (Apache Maven, englisch)
für den Einstieg: Building Java Applications Sample (Gradle-Dokumentation, englisch)
als Nachschlagewerk: Introduction to the Build Lifecycle (Apache Maven, englisch)
als Nachschlagewerk: Gradle User Manual (englisch)
zum Stöbern: Maven Central durchsuchen
weiter in dieser Reihe: Das Build-Tool Maven und Das Build-Tool Gradle
Hinweis zur Nachnutzung als Open Educational Resource (OER)
Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “Build-Tools: vom Quellcode zum auslieferbaren Artefakt” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/build-tools veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/java-advanced/build-tool-maven. Erstellt mit KI-Assistenz; von mir umfassend redaktionell überarbeitet, geprüft und freigegeben. Stand: 12.11.2026.
[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]
