«¿Tu aplicación solo funciona en el IDE? ¡Es hora de solucionarlo!»
\n\nSi alguna vez has programado en Java, seguramente te has encontrado con esta situación: muestras con orgullo tu nuevo proyecto a un amigo, lo ejecutas en IntelliJ IDEA o Eclipse y todo funciona perfectamente. Pero cuando le pasas el proyecto a un colega o intentas ejecutarlo desde la línea de comandos, te encuentras con un ClassNotFoundException o un NoClassDefFoundError. ¿Te suena familiar?
\n\nEn la mayoría de los cursos y tutoriales, enseñan cómo crear un archivo JAR con Maven, pero a menudo omiten un detalle importante: ¿dónde quedan las dependencias?. Un archivo JAR normal solo contiene tu código, mientras que todas las bibliotecas (por ejemplo, Apache Commons, Jackson, JUnit) se quedan fuera. Por eso surge la pregunta que millones de desarrolladores Java hacen en Stack Overflow: «How can I create an executable/runnable JAR with dependencies using Maven?»
\n\nEn este artículo, analizaremos varias formas probadas de crear un JAR ejecutable con dependencias usando Maven. Aprenderás a configurar maven-assembly-plugin, maven-shade-plugin e incluso cómo funciona en Spring Boot. ¡Allá vamos!
\n\n¿Por qué un JAR normal no funciona?
\n\nHagamos un experimento sencillo. Imagina que tienes una aplicación que analiza JSON usando la biblioteca Jackson. Creas un JAR normal con el comando mvn package y luego intentas ejecutarlo:
java -jar my-app.jar\n\nY obtienes algo como:
\n\nException in thread "main" java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/ObjectMapper\n\n¿Por qué sucede esto? Porque Maven, por defecto, empaqueta solo tu código compilado (las clases de la carpeta src/main/java). Todas las dependencias que especificaste en pom.xml permanecen en el repositorio local de Maven (~/.m2/repository). Cuando ejecutas el JAR, la JVM no sabe dónde buscar esas bibliotecas y muestra un error.
La solución es crear un fat JAR (JAR gordo) o uber JAR, que contenga no solo tus clases, sino también todas las dependencias necesarias. Para eso existen plugins especiales de Maven.
\n\nMétodo 1: maven-assembly-plugin (simple y confiable)
\n\nLa forma más popular y sencilla es usar maven-assembly-plugin. Este crea un JAR donde todas las dependencias se descomprimen y se combinan con tus clases. Vamos a configurarlo.
\n\nAñade el siguiente código a tu pom.xml en la sección <build><plugins>:
<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\nImportante: reemplaza com.example.Main con el nombre completo de tu clase que contiene el método main.
Ahora compila el proyecto con el comando:
\n\nmvn clean package\n\nEn la carpeta target aparecerán dos archivos:
- \n
my-app.jar— el JAR normal \n