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.
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.
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.
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.
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 .
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>
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
.
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.
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 )
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
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}.
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>
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 .
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).
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 :)
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)
repo
sous votre dossier racine:votre projet + - pom.xml + - src + - repo
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
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>
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…
Utilisez non-maven-jar-maven-plugin . Fait exactement ce que vous demandiez, sans les inconvénients des autres approches.
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
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.
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>
";
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.
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>
Pour installer le fichier jar tiers qui ne se trouve pas dans le référentiel maven, utilisez maven-install-plugin.
Voici les étapes:
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
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>
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
Une solution étrange j'ai trouvé:
en utilisant Eclipse
à la vôtre, Balint
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>
Même si cela ne correspond pas exactement à votre problème, je vais laisser tomber ceci ici. Mes exigences étaient:
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:
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).
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.
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
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