Construyendo un frasco gordo usando maven

118

Tengo una base de código que quiero distribuir como jar. También depende de frascos externos, que quiero agrupar en el frasco final.

Escuché que esto se puede hacer usando maven-assembly-plug-in, pero no entiendo cómo. ¿Podría alguien señalarme algunos ejemplos?

En este momento, estoy usando frasco de grasa para agrupar el frasco final. Quiero lograr lo mismo usando maven.

bianca
fuente

Respuestas:

143

Nota: si es una aplicación de arranque de primavera, lea el final de la respuesta

Agregue el siguiente complemento a su pom.xml La última versión se puede encontrar en

...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>CHOOSE LATEST VERSION HERE</version>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>assemble-all</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
...

Después de configurar este complemento, ejecute mvn package producirá dos archivos jar: uno que contiene solo las clases del proyecto y un segundo jar grueso con todas las dependencias con el sufijo "-jar-with-dependencies".

si desea una classpathconfiguración correcta en tiempo de ejecución, agregue también el siguiente complemento

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <mainClass>fully.qualified.MainClass</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

Para la aplicación de arranque de primavera, use solo el siguiente complemento (elija la versión adecuada)

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <fork>true</fork>
        <mainClass>${start-class}</mainClass>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>
Jigar Joshi
fuente
1
La versión actual de este complemento es ahora 2.4
guerda
13
Esto ahora está en desuso y en su lugar debería usarse el complemento maven-shadow-plugin. Consulte la respuesta de @phlogratos: stackoverflow.com/a/16222965/274350 .
Richard Neish
2
¿Puede maven-assembly-plugin minimizar el tamaño de fat jar?
May12
1
@Richard ¿Dónde ves que está en desuso? No pude encontrar nada por aquí maven.apache.org/plugins/maven-assembly-plugin
user3833308
3
@ user3833308 "obsoleto" puede ser la palabra incorrecta, pero la documentación en maven.apache.org/plugins/maven-assembly-plugin dice "Si su proyecto quiere empaquetar su artefacto en un uber-jar, el complemento de ensamblaje solo proporciona soporte. Para un mayor control, use el complemento Maven Shade ".
Richard Neish
55

Puede utilizar el complemento maven-shadow-plugin .

Después de configurar el complemento de sombra en su compilación, el comando mvn packagecreará un solo jar con todas las dependencias fusionadas en él.

phlogratos
fuente
9
Esta es ahora la forma correcta de hacerlo. La documentación de maven-assembly-plugin dice: "Si su proyecto quiere empaquetar su artefacto en un uber-jar, el plugin de ensamblaje solo proporciona soporte básico. Para mayor control, use el complemento Maven Shade".
Richard Neish
Pero, ¿cómo tomo ese único .jar y lo uso para publicar?
DanGordon
42

Tal vez desee maven-shade-pluginagrupar dependencias, minimizar el código no utilizado y ocultar las dependencias externas para evitar conflictos.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.1.1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <minimizeJar>true</minimizeJar>
                        <createDependencyReducedPom>true</createDependencyReducedPom>
                        <dependencyReducedPomLocation>
                            ${java.io.tmpdir}/dependency-reduced-pom.xml
                        </dependencyReducedPomLocation>
                        <relocations>
                            <relocation>
                                <pattern>com.acme.coyote</pattern>
                                <shadedPattern>hidden.coyote</shadedPattern>
                            </relocation>
                        </relocations>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Referencias:

gradas
fuente
Si uno se encuentra Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found, simplemente elimínelo <minimizeJar>true</minimizeJar>.
koppor
Si obtiene una excepción "java.lang.SecurityException: resumen de archivo de firma no válido para los atributos principales del manifiesto", esta adición a la sección de configuración anterior ayuda: stackoverflow.com/a/6743609/38368
Danny Varod
12

en realidad, agregando el

<archive>
   <manifest>
    <addClasspath>true</addClasspath>
    <packageName>com.some.pkg</packageName>                     
    <mainClass>com.MainClass</mainClass>
  </manifest>
</archive>

declaración a maven-jar-plugin no agrega la entrada de clase principal al archivo de manifiesto para mí. Tuve que agregarlo al maven-assembly-plugin para obtenerlo en el manifiesto

ameet chaubal
fuente
5

Puede utilizar onejar-maven-plugin para empaquetar. Básicamente, ensambla su proyecto y sus dependencias como un solo jar, incluyendo no solo el archivo jar del proyecto, sino también todas las dependencias externas como un "jar de jarras", por ejemplo

<build>
    <plugins>
        <plugin>
            <groupId>com.jolira</groupId>
            <artifactId>onejar-maven-plugin</artifactId>
                <version>1.4.4</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>one-jar</goal>
                        </goals>
                    </execution>
                </executions>
        </plugin>
    </plugins>
</build>

Nota 1: Las opciones de configuración están disponibles en la página de inicio del proyecto .

Nota 2: Por una razón u otra, el proyecto onejar-maven-plugin no se publica en Maven Central. Sin embargo, jolira.com rastrea el proyecto original y lo publica con el groupId com.jolira.

matsev
fuente
¿Es posible elegir las dependencias con las que desea empaquetar? Por ejemplo, si a.jar y b.jar son frascos externos y quiero empaquetar solo a.jar en el frasco final, ¿es algo posible / configurable?
bianca
También veo que las cosas de un frasco también se empaquetaron en el frasco final. Esto aumentó mucho el tamaño del frasco final. ¿Es posible elegir frascos externos que pretenda incluir en el frasco final? Aquí están los registros de un frasco: pastebin.com/UwniQJ2X
bianca
No sé si se puede configurar lo que está incluido o no. Básicamente, one-jar incluye todas las dependencias especificadas por su proyecto, incluidas las dependencias transitivas, así que sí, es probable que el jar final se vuelva grande si tiene muchas dependencias. One-jar agregará algunos gastos generales para que Java funcione con la estructura "jar of jars".
matsev
2

Una alternativa es utilizar el complemento de sombra de maven para crear un archivo uber-jar.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version> Your Version Here </version>
    <configuration>
            <!-- put your configurations here -->
    </configuration>
    <executions>
            <execution>
                    <phase>package</phase>
                    <goals>
                            <goal>shade</goal>
                    </goals>
            </execution>
    </executions>
</plugin>
Stanislav
fuente