web-dev-qa-db-fra.com

Puis-je ajouter des fichiers jars à maven 2 build classpath sans les installer?

Maven2 me rend folle pendant la phase de développement rapide et sale de maquettes d'expérimentation.

J'ai un fichier pom.xml qui définit les dépendances pour le framework d'applications Web que je souhaite utiliser et je peux rapidement générer des projets de démarrage à partir de ce fichier. Cependant, parfois, je souhaite créer un lien vers une bibliothèque tierce qui n'a pas déjà défini de fichier pom.xml. Par conséquent, plutôt que de créer le fichier pom.xml pour la bibliothèque tierce à la main et de l'installer, et ajouter la dépendance à mon pom.xml, je voudrais simplement dire à Maven: "En plus des dépendances définies, incluez également tous les fichiers jar qui se trouvent dans /lib."

Il semble que cela devrait être simple, mais si c'est le cas, il me manque quelque chose.

Tous les conseils sur la façon de le faire sont grandement appréciés. Bref, s’il existe un moyen simple de pointer maven vers un répertoire /lib et de créer facilement un pom.xml avec tous les fichiers jars fermés mappés sur une dépendance unique, que je pourrais ensuite nommer/installer et se lier à d'un seul coup suffirait également.

681
purple

Problèmes d'approches populaires

La plupart des réponses trouvées sur Internet vous suggèreront soit d'installer la dépendance dans votre référentiel local, soit de spécifier une étendue "système" dans la variable pom et de distribuer la dépendance avec la source de votre projet. Mais ces deux solutions sont réellement imparfaites.

Pourquoi vous ne devriez pas appliquer l'approche "Installer dans Local Repo"

Lorsque vous installez une dépendance sur votre référentiel local, elle y reste. Votre artefact de distribution fera l'affaire tant qu'il aura accès à ce référentiel. Le problème est que dans la plupart des cas, ce référentiel résidera sur votre ordinateur local. Il n'y aura donc aucun moyen de résoudre cette dépendance sur un autre ordinateur. De toute évidence, faire en sorte que votre artefact dépende d'une machine spécifique n'est pas une façon de gérer les choses. Sinon, cette dépendance devra être installée localement sur chaque machine travaillant avec ce projet, ce qui n’est pas mieux.

Pourquoi vous ne devriez pas appliquer l'approche "System Scope"

Les fichiers JAR dont vous dépendez avec l'approche "System Scope" ne sont pas installés dans un référentiel ou attachés à vos packages cible. C'est pourquoi votre paquet de distribution ne pourra pas résoudre cette dépendance lorsqu'il sera utilisé. Je pense que c'est la raison pour laquelle l'utilisation de la portée du système est même devenue obsolète. Quoi qu'il en soit, vous ne voulez pas vous fier à une fonctionnalité obsolète.

La solution de référentiel interne au projet

Après avoir mis ceci dans votre 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>

pour chaque artefact ayant un identifiant de groupe de forme x.y.z Maven inclura l'emplacement suivant dans votre répertoire de projet dans sa recherche d'artefacts:

repo/
| - x/
|   | - y/
|   |   | - z/
|   |   |   | - ${artifactId}/
|   |   |   |   | - ${version}/
|   |   |   |   |   | - ${artifactId}-${version}.jar

Pour en savoir plus sur ce sujet, vous pouvez lire cet article de blog .

Utilisez Maven pour installer sur projet repo

Au lieu de créer cette structure à la main, il est recommandé d’utiliser un plugin Maven pour installer vos fichiers jar en tant qu’artefacts. Donc, pour installer un artefact dans un référentiel de projet dans le dossier repo, exécutez:

mvn install:install-file -DlocalRepositoryPath=repo -DcreateChecksum=true -Dpackaging=jar -Dfile=[your-jar] -DgroupId=[...] -DartifactId=[...] -Dversion=[...]

Si vous choisissez cette approche, vous pourrez simplifier la déclaration du référentiel dans pom pour:

<repository>
    <id>repo</id>
    <url>file://${project.basedir}/repo</url>
</repository>

Un script d'aide

Comme l'exécution de la commande d'installation pour chaque bibliothèque est un peu gênante et propice aux erreurs, j'ai créé un script utilitaire qui installe automatiquement tous les fichiers JAR d'un dossier lib dans un référentiel de projet résoudre toutes les métadonnées (groupId, artifactId, etc.) à partir des noms de fichiers. Le script imprime également les dépendances XML à copier-coller dans votre pom.

Inclure les dépendances dans votre paquet cible

Lorsque vous aurez créé votre référentiel intégré au projet, vous aurez résolu le problème de la répartition des dépendances du projet avec son source. Toutefois, depuis lors, l'artefact cible de votre projet dépendra de fichiers jar non publiés. dans un référentiel, il aura des dépendances insolubles.

Pour résoudre ce problème, je suggère d’inclure ces dépendances dans votre package cible. Vous pouvez le faire avec le Assembly Plugin ou mieux avec le OneJar Plugin . La documentation officielle sur OneJar est facile à comprendre.

581
Nikita Volkov

Pour le code d'élimination uniquement

définissez scope == system et créez simplement un groupId, un artifactId et une version

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

Remarque: les dépendances du système ne sont pas copiées dans le fichier jar/war résultant.
(voir Comment inclure des dépendances de système dans un conflit construit avec maven )

470
Pyrolistical

Vous pouvez créer un référentiel local sur votre projet

Par exemple, si vous avez le dossier libs dans la structure du projet

  • Dans le dossier libs, vous devez créer une structure de répertoires telle que: /groupId/artifactId/version/artifactId-version.jar

  • Dans votre pom.xml, vous devez enregistrer le référentiel

    <repository>
        <id>ProjectRepo</id>
        <name>ProjectRepo</name>
        <url>file://${project.basedir}/libs</url>
    </repository>
    
  • et ajoutez la dépendance comme d'habitude

    <dependency>
        <groupId>groupId</groupId>
        <artifactId>artifactId</artifactId>
        <version>version</version>
    </dependency>
    

C'est tout.

Pour des informations détaillées: Comment ajouter des bibliothèques externes dans Maven

56
Dmytro Boichenko

Remarque: lors de l'utilisation de la portée Système ( comme indiqué sur cette page ), Maven a besoin de chemins absolus.

Si vos fichiers jar se trouvent sous la racine de votre projet, vous souhaitez préfixer vos valeurs systemPath avec $ {basedir}.

30
Ed Brannin

C’est ce que j’ai fait. Cela fonctionne également autour du problème des paquets et fonctionne avec du code extrait.

J'ai créé un nouveau dossier dans le projet. Dans mon cas, j'ai utilisé repo, mais vous pouvez utiliser src/repo.

Dans mon POM, j'avais une dépendance qui ne se trouve dans aucun référentiel public Maven

<dependency>
    <groupId>com.dovetail</groupId>
    <artifactId>zoslog4j</artifactId>
    <version>1.0.1</version>
    <scope>runtime</scope>
</dependency>

J'ai ensuite créé les répertoires suivants repo/com/dovetail/zoslog4j/1.0.1 et copié le fichier JAR dans ce dossier.

J'ai créé le fichier POM suivant pour représenter le fichier téléchargé (cette étape est facultative, mais elle supprime un AVERTISSEMENT) et aide le prochain gars à déterminer par où le fichier a commencé.

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

Deux fichiers facultatifs que je crée sont les sommes de contrôle SHA1 pour le POM et le JAR pour supprimer les avertissements de somme de contrôle manquants.

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

Enfin, j’ajoute à mon fichier pom.xml le fragment suivant qui me permet de faire référence au référentiel local

<repositories>
    <repository>
        <id>project</id>
        <url>file:///${basedir}/repo</url>
    </repository>
</repositories>
14
Archimedes Trajano

Vous devez vraiment mettre en place un cadre via un référentiel et identifier vos dépendances dès le départ. L'utilisation de la portée du système est une erreur courante, car les utilisateurs ne se soucient pas de la gestion des dépendances. Le problème, c’est que, pour ce faire, vous vous retrouvez avec une construction perverse qui ne sera pas affichée dans un état normal. Vous feriez mieux de suivre une approche comme this .

13
Brian Fox

Le plugin d'installation Maven a un usage en ligne de commande pour installer un fichier jar dans le référentiel local. POM est facultatif, mais vous devrez spécifier les éléments GroupId, ArtifactId, Version et Packaging (tous les éléments POM).

12
toad

Voici comment nous ajoutons ou installons 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>

j'ai donné des identifiants groupId et artifactId par défaut car ils sont obligatoires :)

10
Praneel PIDIKITI

J'ai trouvé un autre moyen de le faire, voir ici d'un article de Herok

Pour résumer (désolé pour certains copier/coller)

  • Créez un répertoire repo sous votre dossier racine:
 votre projet 
 + - pom.xml 
 + - src 
 + - repo 
  • Exécutez ceci pour installer le fichier jar dans votre répertoire de dépôt local
 mvn deploy: deploy-fichier -Durl = fichier: /// chemin/vers/votre/projet/référentiel/-Dfichier = mylib-1.0.jar -DgroupId = com.example -DartifactId = mylib -Dpackaging = jar - Dversion = 1,0 
  • Ajoutez ceci votre 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>
8
xbeta

Utiliser <scope>system</scope> est une idée terrible pour des raisons expliquées par d’autres, installer le fichier manuellement dans votre référentiel local rend la construction non reproductible, et utiliser <url>file://${project.basedir}/repo</url> n’est pas une bonne idée non plus car (1) cela peut ne pas être le cas. une URL file bien formée (par exemple, si le projet est extrait dans un répertoire contenant des caractères inhabituels), (2) le résultat est inutilisable si le POM de ce projet est utilisé comme dépendance du projet de quelqu'un d'autre.

En supposant que vous ne souhaitiez pas télécharger l’artefact dans un référentiel public, la suggestion de Simeon concernant un module auxiliaire fait le travail. Mais il existe un moyen plus facile maintenant…

La recommandation

Utilisez non-maven-jar-maven-plugin . Fait exactement ce que vous demandiez, sans les inconvénients des autres approches.

8
Jesse Glick

Après avoir longuement discuté avec les gars de CloudBees à propos du packaging approprié de ce type de fichiers JAR, ils ont fait une bonne proposition intéressante de solution:

Création d'un faux projet Maven qui associe un fichier JAR préexistant en tant qu'artéfact principal et qui s'exécute dans l'installation POM appartenant à l'installation: exécution du fichier d'installation. Voici un exemple d'un tel 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>

Mais pour la mettre en œuvre, la structure du projet existant doit être modifiée. Tout d'abord, vous devriez avoir à l'esprit que pour chaque type de JAR de ce type, un faux projet Maven (module) différent doit être créé. Et vous devez créer un projet Maven parent comprenant tous les sous-modules, à savoir: tous les wrappers JAR et le projet principal existant. La structure pourrait être:

projet racine (il contient le fichier POM parent qui inclut tous les sous-modules avec module Élément XML) (emballage POM)

JAR 1 wrapper Maven child project (emballage POM)

JAR 2 wrapper Maven child project (emballage POM)

projet principal existant des enfants Maven (WAR, JAR, EAR .... packaging)

Lorsque le parent s'exécute via mvn: install ou mvn: l'empaquetage est forcé et les sous-modules seront exécutés. Cela pourrait être considéré comme un inconvénient ici, car la structure du projet devrait être modifiée, mais offre une solution non statique à la fin

6
Simeon Angelov

Le problème avec systemPath est que les fichiers JAR des dépendances ne seront pas distribués le long de vos artefacts en tant que dépendances transitives. Essayez ce que j’ai posté ici: Est-il préférable de modérer vos fichiers jar de projet ou de les mettre dans WEB-INF/lib?

Puis déclarez les dépendances comme d'habitude.

Et s'il vous plaît lire la note de bas de page.

4
mschonaker

Si vous voulez une solution rapide et délicate, vous pouvez procéder comme suit (bien que je ne le recommande pas, sauf pour les projets tests, maven se plaindra longuement que cela n’est pas correct).

Ajoutez une entrée de dépendance pour chaque fichier JAR dont vous avez besoin, de préférence avec un script Perl ou quelque chose de similaire, puis copiez/collez-la dans votre fichier 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>
";
3
Alex Lehmann

Une solution batch rapide et sale (basée sur la réponse d'Alex):

libs.bat

@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^>
)

Exécutez-le comme ceci: libs.bat > libs.txt. Ensuite, ouvrez libs.txt et copiez son contenu en tant que dépendances.

Dans mon cas, je n'avais besoin que des bibliothèques pour compiler mon code, et cette solution était la meilleure à cette fin.

3
lmiguelmh

Ce qui me semble le plus simple, c’est de configurer votre plugin maven-compiler-plugin pour inclure vos fichiers jar personnalisés. Cet exemple chargera tous les fichiers jar dans un répertoire lib.

        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <includes>
                    <include>lib/*.jar</include>
                </includes>
            </configuration>
        </plugin>
3
realgt

Pour installer le fichier jar tiers qui ne se trouve pas dans le référentiel maven, utilisez maven-install-plugin.

Voici les étapes:

  1. Télécharger le fichier jar manuellement à partir de la source (site web)
  2. Créez un dossier et placez-y votre fichier jar
  3. Exécutez la commande ci-dessous pour installer le fichier jar tiers dans votre référentiel Maven local.

mvn install: install-file -Dfile = -DgroupId = -DartifactId = -Dversion = -Dpackaging =

Ci-dessous, par exemple, celui que je l’ai utilisé pour 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 = pot

  1. Dans le fichier pom.xml, incluez la dépendance comme ci-dessous

      <dependency> 
            <groupId>uk.org.simonsite</groupId>
            <artifactId>log4j-rolling-appender</artifactId>
            <version>20150607-2059</version> 
      </dependency>
    
  2. Exécutez la commande mvn clean install pour créer votre package.

Ci-dessous le lien de référence:

https://maven.Apache.org/guides/mini/guide-3rd-party-jars-local.html

2
Andrew TR

Une solution étrange j'ai trouvé:

en utilisant Eclipse

  • créer un projet simple (non maven) Java
  • ajouter une classe principale
  • ajoute tous les pots au classpath
  • exporter le fichier JAR de Runnable (c'est important, car aucun autre moyen de le faire ici)
  • sélectionnez Extraire les bibliothèques requises dans le fichier JAR généré.
  • décider les problèmes de licence
  • tadammm ... installe le pot généré sur votre m2repo
  • ajoutez cette dépendance unique à vos autres projets.

à la vôtre, Balint

2
Balint Pato

Pour ceux qui n'ont pas trouvé de bonne réponse ici, voici ce que nous faisons pour obtenir un bocal avec toutes les dépendances nécessaires. Cette réponse ( --- (https://stackoverflow.com/a/7623805/1084306 ) mentionne l'utilisation du plug-in Maven Assembly mais ne donne pas réellement d'exemple dans la réponse. Et si vous ne lisez pas tout le chemin jusqu'à la fin de la réponse (c'est assez long), vous pouvez le manquer. Ajouter ce qui suit à votre pom.xml va générer 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>
2
Donovan

Même si cela ne correspond pas exactement à votre problème, je vais laisser tomber ceci ici. Mes exigences étaient:

  1. Les pots qui ne peuvent pas être trouvés dans un référentiel Maven en ligne doivent être dans le SVN.
  2. Si un développeur ajoute une autre bibliothèque, les autres développeurs ne devraient pas être dérangés par leur installation manuelle.
  3. Le IDE (NetBeans dans mon cas) devrait pouvoir trouver les sources et les javadocs nécessaires à l'auto-complétion et à l'aide.

Parlons d'abord de (3): le simple fait de placer les pots dans un dossier et de les fusionner dans le dernier pot ne fonctionnera pas ici, car le IDE ne le comprendra pas. Cela signifie que toutes les bibliothèques doivent être installées correctement. Cependant, je ne veux pas que tout le monde l’installe avec "mvn install-file".

Dans mon projet, j'avais besoin de metawidget. Et c'est parti:

  1. Créez un nouveau projet maven (nommez-le "shared-libs" ou quelque chose du genre).
  2. Téléchargez metawidget et extrayez le zip dans src/main/lib.
  3. Le dossier doc/api contient les javadocs. Créez un zip du contenu (doc/api/api.Zip).
  4. Modifier le pom comme ça
  5. Construisez le projet et la bibliothèque sera installée.
  6. Ajoutez la bibliothèque en tant que dépendance à votre projet ou (si vous avez ajouté la dépendance dans le projet shared-libs), ajoutez shared-libs en tant que dépendance pour obtenir toutes les bibliothèques à la fois.

Chaque fois que vous avez une nouvelle bibliothèque, ajoutez simplement une nouvelle exécution et dites à tout le monde de reconstruire le projet (vous pouvez améliorer ce processus avec des hiérarchies de projet).

2
Cephalopod

Cela ne répond pas à la façon de les ajouter à votre POM, et peut-être une évidence, mais ajouterait-il simplement le répertoire lib à votre travail sur les chemins de classes? Je sais que c'est ce que je fais quand j'ai besoin d'un bocal externe que je ne souhaite pas ajouter à mon dépôt Maven.

J'espère que cela t'aides.

0
javamonkey79

J'ai fait allusion à du code python dans un commentaire à la réponse de @alex lehmann's, je le poste donc ici.

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

Ce qui fonctionne dans notre projet est ce que Archimedes Trajano a écrit, mais nous avions dans notre fichier .m2/settings.xml quelque chose comme ceci:

 <mirror>
  <id>nexus</id>
  <mirrorOf>*</mirrorOf>
  <url>http://url_to_our_repository</url>
 </mirror>

et le * devrait être changé en central. Donc, si sa réponse ne fonctionne pas pour vous, vous devriez vérifier votre settings.xml

0
Łukasz Klich