Maven: adicione uma dependência a um jar pelo caminho relativo

232

Eu tenho um jar proprietário que eu quero adicionar ao meu pom como uma dependência.

Mas não quero adicioná-lo a um repositório. O motivo é que eu quero que meus comandos comuns, como mvn compileetc, funcionem imediatamente . (Sem exigir dos desenvolvedores a para adicioná-lo a algum repositório por eles mesmos).

Eu quero que o jar esteja em uma lib de terceiros no controle de origem e vincule a ele pelo caminho relativo do arquivo pom.xml.

Isso pode ser feito? Quão?

flybywire
fonte

Respostas:

343

Eu quero que o jar esteja em uma lib de terceiros no controle de origem e vincule a ele pelo caminho relativo do arquivo pom.xml.

Se você realmente deseja isso (entenda, se você não pode usar um repositório corporativo), meu conselho seria usar um "repositório de arquivos" local para o projeto e não usar uma systemdependência de escopo. O systemescopo deve ser evitado, tais dependências não funcionam bem em muitas situações (por exemplo, na montagem), pois causam mais problemas do que benefícios.

Portanto, declare um repositório local para o projeto:

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

Instale sua biblioteca de terceiros usando install:install-fileo localRepositoryPathparâmetro:

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

Atualização: parece que install:install-fileignora o localRepositoryPathquando estiver usando a versão 2.2 do plugin. No entanto, ele funciona com a versão 2.3 e posterior do plug-in. Portanto, use o nome completo do plug-in para especificar a versão:

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>

documentação do maven-install-plugin

Por fim, declare-o como qualquer outra dependência (mas sem o systemescopo):

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

Esta é a IMHO uma solução melhor do que usar um systemescopo, pois sua dependência será tratada como um bom cidadão (por exemplo, será incluída em uma assembléia e assim por diante).

Agora, devo mencionar que o "caminho certo" para lidar com essa situação em um ambiente corporativo (talvez não seja o caso aqui) seria usar um repositório corporativo.

Pascal Thivent
fonte
2
Esta é uma ótima idéia, mas em Maven 2.2.1, a instalação plug-in parece estar ignorando localRepositoryPath...
Jake
1
Por que declarar um repositório local? Por que não deixá-lo entrar em ~ / .m2 / com o resto.
Leif Gruenwoldt
6
@ leif81 Porque, então, o repositório e as bibliotecas são verificados no repositório SCM -> Qualquer pessoa que faça uma verificação de origem tem tudo o que precisa para criar uma cópia da biblioteca / aplicativo.
Darth Android
6
Eu tive o mesmo problema que o @lemon, que eu consertei basedir/./my-local-repocom um único ..
Brian
2
A embalagem deve ser jar, portanto, -Dpackaging = jar #
Danila Piatov
127

Usando o systemescopo. ${basedir}é o diretório do seu pom.

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

No entanto, é aconselhável que você instale seu jar no repositório e não o comprometa no SCM - afinal, é isso que o maven tenta eliminar.

Bozho
fonte
15
O sistema de escopo deve ser evitado em todos os lugares possíveis. Instalar o JAR no repositório é uma solução melhor ...
Gandalf Stormcrow
14
sim, se possível ele disse explicitamente que não deseja colocá-lo no repositório. Eu adicionei um comentário para ressaltar que essa não é uma boa prática. Mas funciona.
Bozho 9/02/10
groovy, você solução é a mais aceitável até agora eu acho .. Eu descaracterizou totalmente a questão
formiga
Sim - a pergunta em si exclui a melhor resposta. Colocar tudo no seu servidor de controle de fonte única tem pouco a ver com "construir fora da caixa"; antes, tudo precisa ser "controlado". Faça check-in do pom & settings.xml (apontando para o repositório interno ) e use dois servidores para o seu projeto: (1) controle de origem, (2) controle de artefato gerado. Faz tanto sentido fazer o check-in de frascos quanto o check-in de dll (meu antigo corp realmente fazia check-in de frascos e lib.a / .so / .dll. Nosso servidor p4 ficou muito lento depois, alguns hg secretamente usados ​​durante o dia trabalho hoje - problema resolvido?
michael
alguma maneira de especificar um diretório que contenha jars, então não precisamos adicionar todos e cada um como o gradle pode fazer isso?
precisa saber é o seguinte
29

Este é outro método, além da minha resposta anterior em Posso adicionar jars ao maven 2 build classpath sem instalá-los?

Isso contornará o limite ao usar compilações de vários módulos, especialmente se o JAR baixado for referenciado em projetos filhos fora do pai. Isso também reduz o trabalho de configuração criando os arquivos POM e SHA1 como parte da compilação. Ele também permite que o arquivo resida em qualquer lugar do projeto sem corrigir os nomes ou seguir a estrutura do repositório maven.

Isso usa o maven-install-plugin. Para que isso funcione, você precisa configurar um projeto com vários módulos e ter um novo projeto representando a compilação para instalar arquivos no repositório local e garantir que seja o primeiro.

Seu projeto com vários módulos pom.xml ficaria assim:

<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>

O arquivo repository / pom.xml conterá as definições para carregar os JARs que fazem parte do seu projeto. A seguir, alguns trechos do arquivo pom.xml.

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

O empacotamento pom evita que ele faça testes ou compile ou gere qualquer arquivo jar. A descrição do pom.xml está na seção de construção, onde o maven-install-plugin é usado.

<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 mais de um arquivo, basta adicionar mais execuções.

Archimedes Trajano
fonte
Essa é a única coisa que funcionou no meu projeto de vários módulos. A abordagem local do <repositório> por um motivo desconhecido não funcionou. Então obrigado!
Lonzak
10

Isso está funcionando para mim: digamos que tenho essa dependência

<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>

Em seguida, adicione o caminho da classe para a dependência do sistema manualmente, como este

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

Configuração 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
fonte
9

Eu escrevi anteriormente sobre um padrão para fazer isso.

É muito semelhante à solução proposta por Pascal, embora mova todas essas dependências para um módulo de repositório dedicado, para que você não precise repeti-lo em todos os lugares em que a dependência é usada se for uma compilação de vários módulos.

Brett Porter
fonte
6

Basicamente, adicione isso ao 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
fonte
4

nós mudamos para gradle e isso funciona muito melhor em gradle;). apenas especificamos uma pasta na qual podemos colocar jarros para situações temporárias como essa. Ainda temos a maioria dos nossos jarros definidos na seção de gerenciamento de dependência típica (ou seja, o mesmo que maven). Esta é apenas mais uma dependência que definimos.

então basicamente agora podemos colocar qualquer jar que quisermos em nosso diretório lib para testes temporários, se ele não estiver em um repositório maven em algum lugar.

Dean Hiller
fonte
1
Você poderia dar um exemplo de como você fez isso?
Thomas
2

Uma pequena adição à solução postada por Pascal

Quando segui esta rota, recebi um erro no maven ao instalar ojdbc jar.

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

Depois de adicionar -DpomFile, o problema foi resolvido.

$ 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
fonte
0

Você pode usar o eclipse para gerar um arquivo Jar executável: arquivo Export / Jar executável

user1942990
fonte
Não tenho certeza de que está respondendo à pergunta. Ele já tem o arquivo como um frasco.
Johannes Jander
Eclipse suportes uberjar ou frasco com sombra, por isso é uma solução, mas não para maven
Alex Lehmann