Maven: agregue una dependencia a un jar por ruta relativa

232

Tengo un jar propietario que quiero agregar a mi pom como dependencia.

Pero no quiero agregarlo a un repositorio. La razón es que quiero que mis comandos maven habituales, como mvn compile, etc., funcionen de fábrica. (Sin exigir a los desarrolladores que lo agreguen a algún repositorio por sí mismos).

Quiero que el jar esté en una biblioteca de tercera parte en el control de fuente, y enlace a él por ruta relativa desde el archivo pom.xml.

Se puede hacer esto? ¿Cómo?

flybywire
fuente

Respuestas:

343

Quiero que el jar esté en una biblioteca de tercera parte en el control de fuente, y enlace a él por ruta relativa desde el archivo pom.xml.

Si realmente quiere esto (entienda, si no puede usar un repositorio corporativo), entonces mi consejo sería usar un "repositorio de archivos" local para el proyecto y no usar una systemdependencia con ámbito. Se systemdebe evitar el alcance, tales dependencias no funcionan bien en muchas situaciones (por ejemplo, en el ensamblaje), causan más problemas que beneficios.

Entonces, en su lugar, declare un repositorio local para el proyecto:

<repositories>
  <repository>
    <id>my-local-repo</id>
    <url>file://${project.basedir}/my-repo</url>
  </repository>
</repositories>

Instale su lib de terceros install:install-filecon el localRepositoryPathparámetro:

mvn install:install-file -Dfile=<path-to-file> -DgroupId=<myGroup> \ 
                         -DartifactId=<myArtifactId> -Dversion=<myVersion> \
                         -Dpackaging=<myPackaging> -DlocalRepositoryPath=<path>

Actualización: parece que install:install-fileignora localRepositoryPathcuando se utiliza la versión 2.2 del complemento. Sin embargo, funciona con la versión 2.3 y posterior del complemento. Por lo tanto, use el nombre completo del complemento para especificar la versión:

mvn org.apache.maven.plugins:maven-install-plugin:2.3.1:install-file \
                         -Dfile=<path-to-file> -DgroupId=<myGroup> \ 
                         -DartifactId=<myArtifactId> -Dversion=<myVersion> \
                         -Dpackaging=<myPackaging> -DlocalRepositoryPath=<path>

documentación de plugin de instalación de maven

Finalmente, declare como cualquier otra dependencia (pero sin el systemalcance):

<dependency>
  <groupId>your.group.id</groupId>
  <artifactId>3rdparty</artifactId>
  <version>X.Y.Z</version>
</dependency>

Esta es, en mi humilde opinión, una mejor solución que usar un systemalcance, ya que su dependencia será tratada como un buen ciudadano (por ejemplo, se incluirá en una asamblea, etc.).

Ahora, tengo que mencionar que la "forma correcta" de lidiar con esta situación en un entorno corporativo (quizás no sea el caso aquí) sería utilizar un repositorio corporativo.

Pascal Thivent
fuente
2
Esta es una gran idea, pero en Maven 2.2.1, el complemento de instalación parece ignorar localRepositoryPath...
Jake
1
¿Por qué declarar un repositorio local? ¿Por qué no simplemente dejar que entre en ~ / .m2 / con el resto?
Leif Gruenwoldt
66
@ leif81 Porque entonces el repositorio y las bibliotecas se registran en el repositorio de SCM -> Cualquier persona que realice un pago de origen tiene todo lo que necesita para crear una copia de la biblioteca / aplicación.
Darth Android el
66
Tuve el mismo problema que @lemon, que solucioné haciendo basedir/./my-local-repocon un solo en su .lugar.
Brian
2
El empaque tiene que ser frasco, por lo tanto -Dpackaging = jar
Danila Piatov
127

Usando el systemalcance. ${basedir}es el directorio de tu pom.

<dependency>
    <artifactId>..</artifactId>
    <groupId>..</groupId>
    <scope>system</scope>
    <systemPath>${basedir}/lib/dependency.jar</systemPath>
</dependency>

Sin embargo, es aconsejable que instale su jar en el repositorio y no lo confirme en SCM; después de todo, eso es lo que Maven intenta eliminar.

Bozho
fuente
15
El sistema de alcance debe evitarse donde sea posible. Instalar el JAR en el repositorio es una mejor solución ...
Gandalf StormCrow
14
Sí, si es posible. Dijo explícitamente que no quiere ponerlo en el repositorio. Agregué un comentario para señalar que esta no es una buena práctica. Pero funciona.
Bozho
maravilloso, su solución es la más aceptable hasta ahora, supongo ... Leí completamente la pregunta
hormiga
Sí, la pregunta en sí excluye la mejor respuesta. Poner todo en su servidor de control de fuente única tiene poco que ver con "construir fuera de la caja"; más bien, todo tiene que ser "controlado". Haga check-in pom's & settings.xml (señalando al repositorio interno ) y use dos servidores para su proyecto: (1) control de fuente, (2) control de artefactos generado. Tiene tanto sentido comprobar los frascos como lo hace en los dll (mi antiguo cuerpo realmente hizo frascos de registro y lib.a / .so / .dll. Nuestro servidor p4 fue muy lento después, algunos usaron secretamente hg por día . -to-día de trabajo Problema resuelto?
michael
¿Hay alguna forma de especificar un directorio que contenga frascos en su lugar para que no tengamos que agregar todos y cada uno al igual que Gradle puede hacerlo?
Dean Hiller
29

Este es otro método además de mi respuesta anterior en ¿Puedo agregar jarras a maven 2 build classpath sin instalarlas?

Esto superará el límite cuando se utilicen compilaciones de varios módulos, especialmente si se hace referencia al JAR descargado en proyectos secundarios fuera del padre. Esto también reduce el trabajo de configuración al crear los archivos POM y SHA1 como parte de la compilación. También permite que el archivo resida en cualquier parte del proyecto sin corregir los nombres o seguir la estructura del repositorio maven.

Esto utiliza el complemento de instalación de maven. Para que esto funcione, debe configurar un proyecto de varios módulos y tener un nuevo proyecto que represente la compilación para instalar archivos en el repositorio local y asegurarse de que uno sea el primero.

Su proyecto de módulos múltiples pom.xml se vería así:

<packaging>pom</packaging>
<modules>
<!-- The repository module must be first in order to ensure
     that the local repository is populated -->
    <module>repository</module>
    <module>... other modules ...</module>
</modules>

El archivo del repositorio / pom.xml contendrá las definiciones para cargar los archivos JAR que forman parte de su proyecto. Los siguientes son algunos fragmentos del archivo pom.xml.

<artifactId>repository</artifactId>
<packaging>pom</packaging>

El paquete pom evita que esto haga pruebas o compile o genere cualquier archivo jar. La carne de pom.xml está en la sección de compilación donde se usa el complemento de instalación de maven.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-install-plugin</artifactId>
            <executions>
                <execution>
                        <id>com.ibm.db2:db2jcc</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>install-file</goal>
                        </goals>
                        <configuration>
                            <groupId>com.ibm.db2</groupId>
                            <artifactId>db2jcc</artifactId>
                            <version>9.0.0</version>
                            <packaging>jar</packaging>
                            <file>${basedir}/src/jars/db2jcc.jar</file>
                            <createChecksum>true</createChecksum>
                            <generatePom>true</generatePom>
                        </configuration>
                </execution>
                <execution>...</execution>
            </executions>
        </plugin>
    </plugins>
</build>

Para instalar más de un archivo, simplemente agregue más ejecuciones.

Arquímedes Trajano
fuente
Esto es lo único que funcionó para mi proyecto de módulos múltiples. El enfoque <repository> local por una razón desconocida no funcionó. ¡Así que gracias!
Lonzak
10

Esto está funcionando para mí: digamos que tengo esta dependencia

<dependency>
    <groupId>com.company.app</groupId>
    <artifactId>my-library</artifactId>
    <version>1.0</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/lib/my-library.jar</systemPath>
</dependency>

Luego, agregue la ruta de clase para la dependencia de su sistema manualmente de esta manera

<Class-Path>libs/my-library-1.0.jar</Class-Path>

Configuración completa:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
        <archive>
            <manifestEntries>
                <Build-Jdk>${jdk.version}</Build-Jdk>
                <Implementation-Title>${project.name}</Implementation-Title>
                <Implementation-Version>${project.version}</Implementation-Version>
                <Specification-Title>${project.name} Library</Specification-Title>
                <Specification-Version>${project.version}</Specification-Version>
                <Class-Path>libs/my-library-1.0.jar</Class-Path>
            </manifestEntries>
            <manifest>
                <addClasspath>true</addClasspath>
                <mainClass>com.company.app.MainClass</mainClass>
                <classpathPrefix>libs/</classpathPrefix>
            </manifest>
        </archive>
    </configuration>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.5.1</version>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/libs/</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>
RufusSC2
fuente
9

Anteriormente he escrito sobre un patrón para hacer esto.

Es muy similar a la solución propuesta por Pascal, aunque mueve todas esas dependencias a un módulo de repositorio dedicado para que no tenga que repetirlo en todas partes donde se usa la dependencia si se trata de una compilación de varios módulos.

Brett Porter
fuente
6

Básicamente, agregue esto a pom.xml:

...

<repositories>
   <repository>
       <id>lib_id</id>
       <url>file://${project.basedir}/lib</url>
   </repository>
</repositories>

...

<dependencies>
  ...
  <dependency>
      <groupId>com.mylibrary</groupId>
      <artifactId>mylibraryname</artifactId>
      <version>1.0.0</version>
  </dependency>
  ...
</dependencies>
Fulgencio Jara
fuente
4

cambiamos a gradle y esto funciona mucho mejor en gradle;). solo especificamos una carpeta en la que podemos colocar frascos para situaciones temporales como esa. Todavía tenemos la mayoría de nuestras jarras definidas en la sección de gestión de dependencia típicamente (es decir, lo mismo que Maven). Esta es solo una dependencia más que definimos.

así que, básicamente, ahora podemos soltar cualquier jar que queramos en nuestro directorio lib para pruebas temporales si no es un repositorio Maven en alguna parte.

Dean Hiller
fuente
1
¿Podría dar un ejemplo de cómo lo hizo?
Thomas
2

Una pequeña adición a la solución publicada por Pascal

Cuando seguí esta ruta, recibí un error en maven al instalar ojdbc jar.

[INFO] --- maven-install-plugin:2.5.1:install-file (default-cli) @ validator ---
[INFO] pom.xml not found in ojdbc14.jar

Después de agregar -DpomFile, el problema se resolvió.

$ mvn install:install-file -Dfile=./lib/ojdbc14.jar -DgroupId=ojdbc \
   -DartifactId=ojdbc -Dversion=14 -Dpackaging=jar -DlocalRepositoryPath=./repo \
   -DpomFile=~/.m2/repository/ojdbc/ojdbc/14/ojdbc-14.pom
veeseekay
fuente
0

Puede usar eclipse para generar un archivo Jar ejecutable: Exportar / archivo Jar ejecutable

usuario1942990
fuente
No estoy seguro de que eso responda la pregunta. Él ya tiene el archivo como un frasco.
Johannes Jander
Eclipse admite jarra uberjar o sombreada, por lo que es una solución, pero no para maven
Alex Lehmann