„Läuft deine App nur in der IDE? Zeit, das zu ändern!“
\n\nWenn du schon einmal in Java programmiert hast, kennst du die Situation bestimmt: Du zeigst stolz einem Freund dein neues Projekt, startest es in IntelliJ IDEA oder Eclipse – alles funktioniert einwandfrei. Aber sobald du das Projekt an einen Kollegen weitergibst oder versuchst, es über die Kommandozeile zu starten, begrüßt dich ein ClassNotFoundException oder NoClassDefFoundError. Kommt dir bekannt vor?
\n\nIn den meisten Kursen und Tutorials wird gezeigt, wie man mit Maven ein JAR erstellt, aber ein wichtiger Punkt wird oft übersehen: wo bleiben die Abhängigkeiten? Ein normales JAR enthält nur deinen Code, während alle Bibliotheken (wie Apache Commons, Jackson, JUnit) außen vor bleiben. Genau deshalb stellen Millionen Java-Entwickler auf Stack Overflow die Frage: „How can I create an executable/runnable JAR with dependencies using Maven?“
\n\nIn diesem Artikel zeigen wir dir mehrere bewährte Methoden, um ein ausführbares JAR mit Abhängigkeiten mit Maven zu erstellen. Du lernst, wie du das maven-assembly-plugin, das maven-shade-plugin konfigurierst und wie das Ganze in Spring Boot funktioniert. Los geht's!
\n\nWarum funktioniert ein normales JAR nicht?
\n\nMachen wir ein einfaches Experiment. Stell dir vor, du hast eine Anwendung, die JSON mit der Jackson-Bibliothek parst. Du erstellst ein normales JAR mit mvn package und versuchst es zu starten:
java -jar my-app.jar\n\nUnd dann bekommst du so etwas wie:
\n\nException in thread "main" java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/ObjectMapper\n\nWarum passiert das? Weil Maven standardmäßig nur deinen kompilierten Code verpackt (die Klassen aus dem Ordner src/main/java). Alle Abhängigkeiten, die du in der pom.xml angegeben hast, bleiben im lokalen Maven-Repository (~/.m2/repository). Wenn du das JAR startest, weiß die JVM nicht, wo sie diese Bibliotheken finden soll, und gibt einen Fehler aus.
Die Lösung: Erstelle ein Fat JAR (auch Uber JAR genannt), das nicht nur deine Klassen, sondern auch alle benötigten Abhängigkeiten enthält. Genau dafür gibt es spezielle Maven-Plugins.
\n\nMethode 1: maven-assembly-plugin (einfach und zuverlässig)
\n\nDie beliebteste und einfachste Methode ist die Verwendung des maven-assembly-plugin. Es erstellt ein JAR, in dem alle Abhängigkeiten entpackt und mit deinen Klassen zusammengeführt werden. So konfigurierst du es.
\n\nFüge in deiner pom.xml im Abschnitt <build><plugins> folgenden Code hinzu:
<plugin>\n <groupId>org.apache.maven.plugins</groupId>\n <artifactId>maven-assembly-plugin</artifactId>\n <version>3.6.0</version>\n <configuration>\n <descriptorRefs>\n <descriptorRef>jar-with-dependencies</descriptorRef>\n </descriptorRefs>\n <archive>\n <manifest>\n <mainClass>com.example.Main</mainClass>\n </manifest>\n </archive>\n </configuration>\n <executions>\n <execution>\n <id>make-assembly</id>\n <phase>package</phase>\n <goals>\n <goal>single</goal>\n </goals>\n </execution>\n </executions>\n</plugin>\n\nWichtig: Ersetze com.example.Main durch den vollständigen Namen deiner Klasse mit der main-Methode.
Baue nun das Projekt mit folgendem Befehl:
\n\nmvn clean package\n\nIm Ordner target findest du zwei Dateien:
- \n
my-app.jar– das normale \n