Es muy común que necesitemos desarrollar una aplicación en Java cuyo ejecutable es un jar. A la vez, es muy frecuente que estemos usando librería de terceros que necesitamos tener junto a nuestro ejecutable para que la aplicación funcione correctamente. Una solución para evitar tener una gran cantidad de archivos jar, es crear un fat o uber jar.
Basicamente, un fat jar o uber jar, es un archivo auto-suficiente que contiene las clases y dependencies que se necesitan para correr una aplicación. En otras palabras, un único jar que contiene todos las librerias que necesita nuestra aplicación. De esta manera solamente tenemos que compartir un único jar sin importar si utilizamos librerías de terceros.
Este enfoque es muy útil para aplicaciones de escritorio y también para micro-servicios en Java.
Maven
Con maven podemos lograr esto utilizando el plugin maven-shade-plugin
y a la fase package
agregamos el goal shade
. De manera opcional, podemos indicar con este plugin el main class que se ejecutara al iniciar nuestra aplicación.
<project> <dependencies> ... </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.4</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.orthanc.mypackage.Main</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
Gradle
Con gradle es aún más sencillo, solamente tenemos que usar el plugin jar
incluido con la herramienta. De manera opcional también podemos indicar el main-class
que deseamos usar en nuestra aplicación.
dependencies { //my dependencies } jar { from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } manifest { attributes "Main-Class": "com.orthanc.mypackage.Main" } }
Hay algunos fragmentos de codigo en internet y StackOverflow usando configurations.compile.collect
. Sin embargo, no funcionan correctamente con dependencias transitivas o the modulos cuando estas son agregadas usando los scopes implementation
o api
en lugar de compile
. Gradle 6 ha marcado el scope compile
como deprecado y Gradle 7 ya no le da soporte.
Por lo tanto usar configurations.runtimeClasspath.collect
es una mejor alternativa que incluye las dependencias transitivas y de modulos.
Referencias
- https://www.baeldung.com/gradle-fat-jar
- http://maven.apache.org/plugins/maven-shade-plugin/plugin-info.html