java - proyecto - maven project eclipse
¿Puedo agregar archivos jar a maven 2 build classpath sin instalarlos? (23)
Maven2 me está volviendo loco durante la fase de desarrollo de la experimentación / maqueta rápida y sucia.
Tengo un archivo pom.xml
que define las dependencias para el marco de la aplicación web que quiero usar, y puedo generar rápidamente proyectos de inicio a partir de ese archivo. Sin embargo, a veces quiero enlazar a una biblioteca de terceros que aún no tiene un archivo pom.xml
definido, así que en lugar de crear el archivo pom.xml
para la biblioteca de terceros a mano e instalarlo, y agregar la dependencia a mi pom.xml
, solo me gustaría decirle a Maven: "Además de mis dependencias definidas, incluye cualquier tarro que esté en /lib
también".
Parece que esto debería ser simple, pero si lo es, me estoy perdiendo algo.
Cualquier sugerencia sobre cómo hacer esto es muy apreciada. Aparte de eso, si hay una forma sencilla de apuntar a maven a un directorio /lib
y crear fácilmente un pom.xml
con todos los pom.xml
adjuntos asignados a una única dependencia a la que luego podría nombrar / instalar y vincular de una sola vez También basta.
Problemas de los enfoques populares.
La mayoría de las respuestas que encontrará en Internet le sugerirán que instale la dependencia en su repositorio local o que especifique un alcance de "sistema" en el pom
y distribuya la dependencia con la fuente de su proyecto. Pero ambas soluciones son realmente defectuosas.
¿Por qué no debería aplicar el enfoque "Instalar en Repo local"?
Cuando instala una dependencia en su repositorio local, permanece allí. Su artefacto de distribución funcionará bien siempre que tenga acceso a este repositorio. El problema es que, en la mayoría de los casos, este repositorio residirá en su máquina local, por lo que no habrá forma de resolver esta dependencia en ninguna otra máquina. Claramente, hacer que tu artefacto dependa de una máquina específica no es una forma de manejar las cosas. De lo contrario, esta dependencia deberá instalarse localmente en todas las máquinas que trabajen con ese proyecto, lo que no es mejor.
¿Por qué no debería aplicar el enfoque del "alcance del sistema"?
Los frascos de los que depende con el enfoque "Alcance del sistema" no se instalan en ningún repositorio ni se adjuntan a sus paquetes de destino. Es por eso que su paquete de distribución no tendrá una manera de resolver esa dependencia cuando se use. Esa creo que fue la razón por la cual el uso del alcance del sistema incluso quedó en desuso. De todos modos, no quieres confiar en una característica obsoleta.
La solución de repositorio estático en el proyecto.
Después de poner esto en tu pom
:
<repository>
<id>repo</id>
<releases>
<enabled>true</enabled>
<checksumPolicy>ignore</checksumPolicy>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<url>file://${project.basedir}/repo</url>
</repository>
para cada artefacto con un ID de grupo de la forma xyz
Maven incluirá la siguiente ubicación dentro del directorio de su proyecto en su búsqueda de artefactos:
repo/
| - x/
| | - y/
| | | - z/
| | | | - ${artifactId}/
| | | | | - ${version}/
| | | | | | - ${artifactId}-${version}.jar
Para más detalles sobre esto, puedes leer esta publicación de blog .
Usa Maven para instalar para proyectar repo
En lugar de crear esta estructura a mano, recomiendo usar un complemento de Maven para instalar tus archivos jar como artefactos. Entonces, para instalar un artefacto en un repositorio dentro del proyecto en la carpeta repo
ejecute:
mvn install:install-file -DlocalRepositoryPath=repo -DcreateChecksum=true -Dpackaging=jar -Dfile=[your-jar] -DgroupId=[...] -DartifactId=[...] -Dversion=[...]
Si elige este enfoque, podrá simplificar la declaración del repositorio en pom
para:
<repository>
<id>repo</id>
<url>file://${project.basedir}/repo</url>
</repository>
Un guion de ayuda
Dado que la ejecución del comando de instalación para cada lib es un poco molesta y definitivamente propensa a errores, he creado una secuencia de comandos de utilidad que instala automáticamente todos los archivos jar de una carpeta lib
en un repositorio de proyectos, mientras resuelvo automáticamente todos los metadatos (ID de grupo, ID de artefacto y etc.) De nombres de archivos. El script también imprime las dependencias xml para que las copie y pegue en su pom
.
Incluye las dependencias en tu paquete objetivo
Cuando haya creado su repositorio en el proyecto, habrá resuelto el problema de distribuir las dependencias del proyecto con su origen, pero desde entonces el artefacto objetivo de su proyecto dependerá de los archivos no publicados, por lo que cuando instale Para un repositorio tendrá dependencias sin resolución.
Para superar este problema, sugiero incluir estas dependencias en su paquete de destino. Esto se puede hacer con el complemento de ensamblaje o mejor con el complemento de OneJar . La documentación oficial sobre OneJar es fácil de entender.
Aludí a un código python en un comentario a la respuesta de @alex lehmann''s, así que lo estoy publicando aquí.
def AddJars(jarList):
s1 = ''''
for elem in jarList:
s1+= """
<dependency>
<groupId>local.dummy</groupId>
<artifactId>%s</artifactId>
<version>0.0.1</version>
<scope>system</scope>
<systemPath>${project.basedir}/manual_jars/%s</systemPath>
</dependency>/n"""%(elem, elem)
return s1
Así es como agregamos o instalamos un jar local.
<dependency>
<groupId>org.example</groupId>
<artifactId>iamajar</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/iamajar.jar</systemPath>
</dependency>
Di algunos GroupId y ArtifactId predeterminados porque son obligatorios :)
Aunque no se ajusta exactamente a tu problema, dejaré esto aquí. Mis requerimientos fueron:
- Los tarros que no se pueden encontrar en un repositorio de Maven en línea deben estar en el SVN.
- Si un desarrollador agrega otra biblioteca, los otros desarrolladores no deberían molestarse en instalarlos manualmente.
- El IDE (NetBeans en mi caso) debería poder encontrar las fuentes y javadocs para proporcionar autocompletado y ayuda.
Primero hablemos de (3): el simple hecho de tener los frascos en una carpeta y de algún modo fusionarlos en el frasco final no funcionará, ya que el IDE no lo entenderá. Esto significa que todas las bibliotecas deben estar instaladas correctamente. Sin embargo, no quiero que todo el mundo lo instale utilizando "mvn install-file".
En mi proyecto necesitaba metawidget. Aquí vamos:
- Crea un nuevo proyecto de maven (llámalo "shared-libs" o algo así).
- Descargue el metawidget y extraiga el zip en src / main / lib.
- La carpeta doc / api contiene los javadocs. Crea un zip del contenido (doc / api / api.zip).
- Modifica el pom asi
- Construye el proyecto y se instalará la biblioteca.
- Agregue la biblioteca como una dependencia a su proyecto o (si agregó la dependencia en el proyecto de bibliotecas compartidas) agregue las bibliotecas compartidas como dependencia para obtener todas las bibliotecas a la vez.
Cada vez que tenga una nueva biblioteca, solo agregue una nueva ejecución y diga a todos que vuelvan a construir el proyecto (puede mejorar este proceso con jerarquías de proyectos).
Después de tener una larga discusión con los chicos de CloudBees sobre el empaquetado adecuado de este tipo de JAR, hicieron una buena propuesta interesante para una solución:
Creación de un proyecto falso de Maven que adjunta un JAR preexistente como artefacto primario, ejecutándose en la instalación de POM perteneciente: ejecución del archivo de instalación. Aquí hay un ejemplo de tales kinf de POM:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>image-util-id</id>
<phase>install</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${basedir}/file-you-want-to-include.jar</file>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<packaging>jar</packaging>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Pero para implementarlo, la estructura existente del proyecto debe ser cambiada. Primero, debe tener en cuenta que para cada tipo de JAR se deben crear diferentes proyectos (módulos) falsos de Maven. Y debe crearse un proyecto principal de Maven que incluya todos los submódulos que son: todos los envoltorios JAR y el proyecto principal existente. La estructura podría ser:
proyecto raíz (este contiene el archivo POM principal e incluye todos los submódulos con el elemento XML del módulo ) (empaquetado POM)
Envase JAR 1 proyecto Maven child (embalaje POM)
JAR 2 wrapper Maven child project (embalaje POM)
Proyecto principal de Maven child existente (WAR, JAR, EAR .... embalaje)
Cuando el padre se ejecuta a través de mvn: install o mvn: packaging es forzado y se ejecutarán los submódulos. Esto podría ser una desventaja aquí, ya que la estructura del proyecto debe cambiarse, pero ofrece una solución no estática al final.
El problema con systemPath
es que los systemPath
las dependencias no se distribuirán a lo largo de sus artefactos como dependencias transitivas. Pruebe lo que he publicado aquí: ¿Es mejor Mavenize los archivos jar de su proyecto o ponerlos en WEB-INF / lib?
Luego declara las dependencias como de costumbre.
Y por favor lea la nota al pie de página.
Encontré otra forma de hacer esto, vea aquí de una publicación de Heroku
Para resumir (disculpe algo de copiar y pegar)
- Cree un directorio de
repo
en su carpeta raíz:
yourproject +- pom.xml +- src +- repo
- Ejecuta esto para instalar el jar en tu directorio repo local
mvn deploy:deploy-file -Durl=file:///path/to/yourproject/repo/ -Dfile=mylib-1.0.jar -DgroupId=com.example -DartifactId=mylib -Dpackaging=jar -Dversion=1.0
- Añade este tu
pom.xml
:
<repositories> <!--other repositories if any--> <repository> <id>project.local</id> <name>project</name> <url>file:${project.basedir}/repo</url> </repository> </repositories> <dependency> <groupId>com.example</groupId> <artifactId>mylib</artifactId> <version>1.0</version> </dependency>
Esto es lo que he hecho, también soluciona el problema del paquete y funciona con el código desprotegido.
Creé una nueva carpeta en el proyecto en mi caso. Utilicé repo
, pero siéntase libre de usar src/repo
En mi POM tuve una dependencia que no se encuentra en ningún repositorio público
<dependency>
<groupId>com.dovetail</groupId>
<artifactId>zoslog4j</artifactId>
<version>1.0.1</version>
<scope>runtime</scope>
</dependency>
Luego creé los siguientes directorios repo/com/dovetail/zoslog4j/1.0.1
y copié el archivo JAR en esa carpeta.
Creé el siguiente archivo POM para representar el archivo descargado (este paso es opcional, pero elimina una ADVERTENCIA) y ayuda al siguiente tipo a averiguar de dónde obtuve el archivo.
<?xml version="1.0" encoding="UTF-8" ?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dovetail</groupId>
<artifactId>zoslog4j</artifactId>
<packaging>jar</packaging>
<version>1.0.1</version>
<name>z/OS Log4J Appenders</name>
<url>http://dovetail.com/downloads/misc/index.html</url>
<description>Apache Log4j Appender for z/OS Logstreams, files, etc.</description>
</project>
Dos archivos opcionales que creo son las sumas de comprobación SHA1 para el POM y el JAR para eliminar las advertencias de suma de comprobación faltantes.
shasum -b < repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.jar /
> repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.jar.sha1
shasum -b < repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.pom /
> repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.pom.sha1
Finalmente agrego el siguiente fragmento a mi pom.xml que me permite referirme al repositorio local
<repositories>
<repository>
<id>project</id>
<url>file:///${basedir}/repo</url>
</repository>
</repositories>
Esto no responde a cómo agregarlos a tu POM, y puede que no sea un pan comido, pero ¿simplemente agregar el directorio lib a tu classpath funciona? Sé que eso es lo que hago cuando necesito un frasco externo que no quiero agregar a mis repositorios de Maven.
Espero que esto ayude.
Lo que funciona en nuestro proyecto es lo que escribió Arquímedes Trajano, pero tuvimos en nuestro .m2 / settings.xml algo como esto:
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://url_to_our_repository</url>
</mirror>
y el * debe cambiarse a central. Entonces, si su respuesta no funciona para usted, debe revisar su configuración.xml
Lo que me parece más simple es simplemente configurar tu plugin compilador de maven para incluir tus archivos personalizados. Este ejemplo cargará cualquier archivo jar en un directorio lib.
@ECHO OFF
FOR %%I IN (*.jar) DO (
echo ^<dependency^>
echo ^<groupId^>local.dummy^</groupId^>
echo ^<artifactId^>%%I^</artifactId^>
echo ^<version^>0.0.1^</version^>
echo ^<scope^>system^</scope^>
echo ^<systemPath^>${project.basedir}/lib/%%I^</systemPath^>
echo ^</dependency^>
)
Nota: Al usar el alcance del sistema ( como se menciona en esta página ), Maven necesita rutas absolutas.
Si sus archivos jar están bajo la raíz de su proyecto, querrá prefijar los valores de su systemPath con $ {basedir}.
Para aquellos que no encontraron una buena respuesta aquí, esto es lo que estamos haciendo para obtener un frasco con todas las dependencias necesarias en él. Esta respuesta ( https://.com/a/7623805/1084306 ) menciona el uso del complemento de Ensamblaje de Maven pero en realidad no da un ejemplo en la respuesta. Y si no lee hasta el final de la respuesta (es bastante largo), puede que la pierda. Al agregar lo siguiente a su pom.xml se generará target/${PROJECT_NAME}-${VERSION}-jar-with-dependencies.jar
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<!-- get all project dependencies -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- MainClass in mainfest make a executable jar -->
<archive>
<manifest>
<mainClass>my.package.mainclass</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Para instalar el jar de terceros que no está en el repositorio de maven, use maven-install-plugin.
A continuación se presentan los pasos:
- Descargue el archivo jar manualmente desde la fuente (sitio web)
- Crea una carpeta y coloca tu archivo jar en ella.
- Ejecute el siguiente comando para instalar el jar de terceros en su repositorio local de maven
mvn install: install-file -Dfile = -DgroupId = -DartifactId = -Dversion = -Dpackaging =
A continuación se muestra, por ejemplo, uno que usé para simonsite log4j
mvn install: install-file -Dfile = / Users / athanka / git / MyProject / repo / log4j-rolling-appender.jar -DgroupId = uk.org.simonsite -DartifactId = log4j-rolling-appender -Dversion = 20150607-2059 - Dpackaging = jar
En el pom.xml incluye la dependencia de la siguiente manera
<dependency> <groupId>uk.org.simonsite</groupId> <artifactId>log4j-rolling-appender</artifactId> <version>20150607-2059</version> </dependency>
Ejecute el comando mvn clean install para crear su paquete
A continuación se muestra el enlace de referencia:
https://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html
Puedes crear un repositorio local en tu proyecto.
Por ejemplo, si tiene carpeta libs
en la estructura del proyecto
En la carpeta
libs
debe crear una estructura de directorios como:/groupId/artifactId/version/artifactId-version.jar
En tu pom.xml debes registrar repositorio
<repository> <id>ProjectRepo</id> <name>ProjectRepo</name> <url>file://${project.basedir}/libs</url> </repository>
y agrega dependencia como siempre
<dependency> <groupId>groupId</groupId> <artifactId>artifactId</artifactId> <version>version</version> </dependency>
Eso es todo.
Para información detallada: Cómo agregar bibliotecas externas en Maven
Realmente debería tener un marco en su lugar a través de un repositorio e identificar sus dependencias por adelantado. Usar el alcance del sistema es un error común que la gente usa, porque "no les importa la administración de dependencias". El problema es que al hacer esto terminas con una construcción de experto pervertido que no se mostrará en condiciones normales. Sería mejor seguir un enfoque como this .
Si desea una solución rápida y sucia, puede hacer lo siguiente (aunque no lo recomiendo para nada excepto para proyectos de prueba, Maven se quejará de que esto no es correcto).
Agregue una entrada de dependencia para cada archivo jar que necesite, de preferencia con un script perl o algo similar y cópielo / péguelo en su archivo pom.
#! /usr/bin/perl
foreach my $n (@ARGV) {
$n=~s@.*/@@;
print "<dependency>
<groupId>local.dummy</groupId>
<artifactId>$n</artifactId>
<version>0.0.1</version>
<scope>system</scope>
<systemPath>/${project.basedir}/lib/$n</systemPath>
</dependency>
";
Solo quería una solución rápida y sucia ... No pude ejecutar el script de Nikita Volkov: error de sintaxis + requiere un formato estricto para los nombres de los archivos jar.
Hice este script de Perl que funciona con cualquier formato para los nombres de archivos jar, y genera las dependencias en un xml para que pueda copiarse directamente en un pom.
Si desea usarlo, asegúrese de entender lo que hace el script, es posible que deba cambiar la carpeta lib
y el valor para el groupId
o el groupId
...
#!/usr/bin/perl
use strict;
use warnings;
open(my $fh, ''>'', ''dependencies.xml'') or die "Could not open file ''dependencies.xml'' $!";
foreach my $file (glob("lib/*.jar")) {
print "$file/n";
my $groupId = "my.mess";
my $artifactId = "";
my $version = "0.1-SNAPSHOT";
if ($file =~ ///([^//]*?)(-([0-9v/._]*))?/.jar$/) {
$artifactId = $1;
if (defined($3)) {
$version = $3;
}
`mvn install:install-file -Dfile=$file -DgroupId=$groupId -DartifactId=$artifactId -Dversion=$version -Dpackaging=jar`;
print $fh "<dependency>/n/t<groupId>$groupId</groupId>/n/t<artifactId>$artifactId</artifactId>/n/t<version>$version</version>/n</dependency>/n";
print " => $groupId:$artifactId:$version/n";
} else {
print "##### BEUH.../n";
}
}
close $fh;
Una extraña solución que encontré:
utilizando Eclipse
- crear proyecto java simple (no maven)
- añadir una clase principal
- añadir todos los frascos a la ruta de clases
- exportar Runnable JAR (es importante, porque no hay otra manera de hacerlo)
- seleccione Extraer las bibliotecas requeridas en el JAR generado
- decidir los problemas de licencia
- tadammm ... instala el jar generado en tu m2repo
- Añade esta dependencia única a tus otros proyectos.
saludos balint
Una solución por lotes rápida y sucia (basada en la respuesta de Alex):
libs.bat
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<includes>
<include>lib/*.jar</include>
</includes>
</configuration>
</plugin>
libs.bat > libs.txt
: libs.bat > libs.txt
. Luego abra libs.txt
y copie su contenido como dependencias.
En mi caso, solo necesitaba las bibliotecas para compilar mi código, y esta solución era la mejor para ese propósito.
Usar <scope>system</scope>
es una idea terrible por razones explicadas por otros, instalar el archivo manualmente en su repositorio local hace que la compilación sea irreproducible, y usar <url>file://${project.basedir}/repo</url>
tampoco es una buena idea porque (1) puede que no sea una URL de file
bien formada (por ejemplo, si el proyecto está protegido en un directorio con caracteres inusuales), (2) el resultado es inutilizable si el POM de este proyecto Se utiliza como una dependencia del proyecto de otra persona.
Suponiendo que no está dispuesto a cargar el artefacto en un repositorio público, la sugerencia de Simeon de un módulo de ayuda hace el trabajo. Pero ahora hay una manera más fácil ...
La recomendación
Utilice non-maven-jar-maven-plugin . Hace exactamente lo que estaba pidiendo, sin ninguno de los inconvenientes de los otros enfoques.
El complemento de instalación de Maven tiene uso de la línea de comandos para instalar un jar en el repositorio local, POM es opcional, pero tendrá que especificar GroupId, ArtifactId, Version and Packaging (todo el material de POM).
Solo para código de tirar
establece scope == system y simplemente crea un GroupId, artifactId y una versión
<dependency>
<groupId>org.swinglabs</groupId>
<artifactId>swingx</artifactId>
<version>0.9.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/swingx-0.9.3.jar</systemPath>
</dependency>
Nota: las dependencias del sistema no se copian en el archivo jar / war resultante
(ver Cómo incluir dependencias del sistema en la guerra construida con maven )