Encontré el plugin maven-shade-plugin que se usa en el pom.xml de alguien. Nunca he usado el plugin maven-shade-plugin antes (y soy un Maven n00b), así que traté de entender la razón para usar esto y lo que hace.
Miré los documentos de Maven , sin embargo, no puedo entender esta declaración:
"Este complemento proporciona la capacidad de empaquetar el artefacto en un uber-jar, incluidas sus dependencias y sombrear, es decir, cambiar el nombre de los paquetes de algunas de las dependencias".
La documentación en la página no parece muy amigable para los novatos.
¿Qué es un "uber jar"? ¿Por qué alguien querría hacer uno? ¿Cuál es el punto de renombrar los paquetes de las dependencias? Traté de revisar los ejemplos en la página apache de maven-shade-plugin como "Seleccionar contenido para Uber Jar", pero aún no puedo entender lo que se está logrando con "sombreado".
Se agradecería cualquier puntero a ejemplos ilustrativos / casos de uso (con una explicación de por qué se requería sombreado en este caso, qué problema está resolviendo). Por último, ¿cuándo debo usar el complemento maven-shade-plugin?
fuente
s/reallocation/relocation/
en el comentario anteriorRespuestas:
Uber JAR, en resumen, es un JAR que contiene todo.
Normalmente en Maven, confiamos en la gestión de dependencias. Un artefacto contiene solo las clases / recursos de sí mismo. Maven será responsable de averiguar todos los artefactos (JAR, etc.) que el proyecto dependerá de cuándo se construya el proyecto.
Un uber-jar es algo que toma todas las dependencias, extrae el contenido de las dependencias y las coloca con las clases / recursos del proyecto en un gran JAR. Al tener tal uber-jar, es fácil de ejecutar, ya que solo necesitará un JAR grande en lugar de toneladas de JAR pequeños para ejecutar su aplicación. También facilita la distribución en algunos casos.
Solo una nota al margen. Evite usar uber-jar como dependencia de Maven, ya que está arruinando la función de resolución de dependencia de Maven. Normalmente, creamos uber-jar solo para el artefacto final para la implementación real o para la distribución manual, pero no para colocarlo en el repositorio de Maven.
Actualización: Acabo de descubrir que no he respondido una parte de la pregunta: "¿Cuál es el punto de renombrar los paquetes de las dependencias?". Aquí hay algunas actualizaciones breves y con suerte ayudará a las personas que tengan preguntas similares.
Crear uber-jar para facilitar la implementación es un caso de uso del complemento de sombra. También hay otros casos de uso comunes que implican el cambio de nombre del paquete.
Por ejemplo, estoy desarrollando una
Foo
biblioteca, que depende de una versión específica (por ejemplo, 1.0) de laBar
biblioteca. Suponiendo que no puedo hacer uso de otra versión deBar
lib (debido a un cambio de API u otros problemas técnicos, etc.). Si simplemente declaroBar:1.0
comoFoo
dependencia de Maven, es posible caer en un problema: unQux
proyecto depende deFoo
, y tambiénBar:2.0
(y no puede usarloBar:1.0
porqueQux
necesita usar una nueva funciónBar:2.0
). Aquí está el dilema: ¿deberíaQux
usarBar:1.0
(quéQux
código no funcionará) oBar:2.0
(quéFoo
código no funcionará)?Para resolver este problema, el desarrollador de
Foo
puede elegir usar el complemento de sombra para cambiar el nombre de su usoBar
, de modo que todas las clases enBar:1.0
jar estén incrustadas enFoo
jar, y el paquete de lasBar
clases incrustadas cambie decom.bar
acom.foo.bar
. Al hacerlo,Qux
puede depender de forma seguraBar:2.0
porque ahoraFoo
ya no dependeBar
y está utilizando su propia copia "alterada"Bar
ubicada en otro paquete.fuente
jar-with-dependency
descriptor incorporado . Para el problema de la solución de dependencia usando uber-jar, ya he mencionado en mi respuesta: No use uber-jar como dependencia, punto. Un poco más en detalle: antes de crear el uber-jar, debe tener un proyecto normal con dependencia normal. Ese artefacto original es el que debes usar como dependencia (en lugar del uber-jar)Class.forName
de funcionar?Me preguntaba recientemente por qué Elasticsearch sombrea y reubica algunas (pero no todas) de sus dependencias. Aquí hay una explicación del responsable del proyecto, @kimchy :
- https://github.com/elasticsearch/elasticsearch/issues/2091#issuecomment-7156766
Y otro aquí de drewr :
- https://github.com/elasticsearch/elasticsearch/pull/3244#issuecomment-20125452
Entonces, ese es un caso de uso. En cuanto a un ejemplo ilustrativo, a continuación se muestra cómo se utiliza maven-shade-plugin en pom.xml de elasticsearch (v0.90.5). Las
artifactSet::include
líneas le indican qué dependencias extraer en el uber JAR (básicamente, se descomprimen y se vuelven a empaquetar junto con las propias clases de elasticsearch cuando se produce el jar de elasticsearch de destino. solo un archivo ZIP que contiene las clases, los recursos, etc. del programa y algunos metadatos. Puede extraer uno para ver cómo se combina).Las
relocations::relocation
líneas son similares, excepto que en cada caso también aplican las sustituciones especificadas a las clases de la dependencia; en este caso, las clasificamosorg.elasticsearch.common
.Finalmente, la
filters
sección excluye algunas cosas del JAR de destino que no deberían estar allí, como metadatos JAR, archivos de construcción de ant, archivos de texto, etc. que están empaquetados con algunas dependencias, pero que no pertenecen a un JAR superior.fuente
Pequeña advertencia
Aunque eso no describe por qué a uno le gustaría usar el plugin maven-shade-plugin (ya que la respuesta seleccionada lo describe bastante bien), me gustaría señalar que tuve problemas con él. Cambió el JAR (ya que eso es lo que está haciendo) y causó una regresión en mi software.
Entonces, en lugar de usar esto (o el plugin maven-jarjar-plugin), he usado el binario de JarJar que parece funcionar sin problemas.
Estoy publicando aquí mi solución, ya que me tomó un tiempo encontrar una solución decente.
Archivo JAR de Downlaod JarJar
Puede descargar el jar desde aquí: https://code.google.com/p/jarjar/ En el menú de la izquierda tiene un enlace para descargarlo.
Cómo usar JarJar para reubicar las clases de un JAR de un paquete a otro
En este ejemplo, cambiaremos el paquete de "com.fasterxml.jackson" a "io.kuku.dependencies.com.fasterxml.jackson". - El JAR de origen se llama "jackson-databind-2.6.4.jar" y el nuevo JAR modificado (objetivo) se llama "kuku-jackson-databind-2.6.4.jar". - El archivo JAR "jarjar" está en la versión 1.4
Cree un archivo "rules.txt". El contenido del archivo debe ser (ver el período anterior al carácter '@'): regla com.fasterxml.jackson. ** io.kuku.dependencies.com.fasterxml.jackson. @ 1
Ejecute el siguiente comando: java -jar jarjar-1.4.jar process rules.txt jackson-databind-2.6.4.jar kuku-jackson-databind-2.6.4.jar
Instalar los JAR modificados en el repositorio local
En este caso, estoy instalando 3 archivos ubicados en la carpeta "c: \ my-jars \".
mvn install: install-file -Dfile = C: \ my-jars \ kuku-jackson-annotations-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-annotations -Dversion = 2.6.4 - Dpackaging = jar
mvn install: install-file -Dfile = C: \ my-jars \ kuku-jackson-core-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-core -Dversion = 2.6.4 - Dpackaging = jar
mvn install: install-file -Dfile = C: \ my-jars \ kuku-jackson-databind-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-annotations -Dversion = 2.6.4 - Dpackaging = jar
Usando los JAR modificados en el pom del proyecto
En este ejemplo, este es el elemento "dependencias" en los proyectos pom:
fuente
Creo que un ejemplo de la necesidad de un jar "sombreado" es una función AWS Lambda. Parece que solo le permiten cargar 1 jar, no una colección completa de .jars como la que encontraría en un archivo .war típico. Por lo tanto, crear un único .jar con todas las dependencias del proyecto le permite hacer esto.
fuente