Différence entre la compilation de la portée maven et celle fournie pour l'emballage JAR

260

Quelle est la différence entre la portée maven compileet le providedmoment où l'artefact est créé en tant que JAR? Si c'était WAR, je comprendrais - l'artefact serait inclus ou non dans WEB-INF / lib. Mais dans le cas d'un JAR, cela n'a pas d'importance - les dépendances ne sont pas incluses. Ils doivent être sur classpath lorsque leur portée est compileou provided. Je sais que les provideddépendances ne sont pas transitives - mais est-ce seulement une différence?

emstol
la source

Réponses:

289

Du Maven Doc :

  • compiler

    Il s'agit de la portée par défaut, utilisée si aucune n'est spécifiée. Les dépendances de compilation sont disponibles dans tous les chemins de classe d'un projet. En outre, ces dépendances sont propagées aux projets dépendants.

  • à condition de

    Cela ressemble beaucoup à la compilation, mais indique que vous vous attendez à ce que le JDK ou un conteneur fournisse la dépendance au moment de l'exécution. Par exemple, lors de la création d'une application Web pour Java Enterprise Edition, vous devez définir la dépendance sur l'API Servlet et les API Java EE associées sur la portée fournie car le conteneur Web fournit ces classes. Cette portée est uniquement disponible sur la compilation et le chemin de classe de test et n'est pas transitive.

Résumer:

  • les dépendances ne sont pas transitives (comme vous l'avez mentionné)
  • la portée fournie n'est disponible que sur le chemin de classe de compilation et de test, tandis que la portée de compilation est disponible dans tous les chemins de classe.
  • les dépendances fournies ne sont pas packagées
Jacob
la source
5
Oui je sais. Mais je réfléchis à la différence dans les champs d'application dans le JAR packagingcontexte. Maven doc n'en parle pas. J'utilise Maven depuis un certain temps, mais je me suis déjà posé des questions à ce sujet :) Il semble donc que dans le JAR packagingcontexte, il n'y a pas de différence entre compileet provided(sauf transition de dépendance). Ai-je raison?
emstol
3
@Jacob que signifie "alors que la portée de compilation est disponible dans tous les chemins de classe ."?
Geek
1
Je pense que "NOT Transitive" est le gros problème ici. Parce que l'enfer de la dépendance est quelque chose auquel les développeurs sont confrontés très fréquemment et la portée fournie l'empêche de fonctionner et jouer avec d'autres versions est crucial.
Seetharamani Tmr
2
Je pense que la différence est sur la phase d'emballage. Avec la compilation, il inclura le pot dans la guerre finale ou le pot (tel que le pot exécutable de démarrage à ressort), et les résultats fournis ne le peuvent pas. Étant donné que le fichier jar fourni peut être fourni par un conteneur Web (tel que placé dans le dossier ext lib), il n'est pas dans le package war s'il n'est pas dépendant d'autres étendues, compilation, exécution.
Addo Zhang
1
@emstol Pour en revenir à votre question initiale, vous avez raison de dire que dans le cas du JAR, les dépendances ne sont pas regroupées dans le JAR lui-même. Mais dans maven, un emballage JAR signifie que vous voulez qu'il soit utilisé comme bibliothèque. Dès que vous l'importez dans un autre projet maven, les dépendances transitives seront apportées si la portée est compileet ne le seront pas si la portée est provided.
LeoLuz
291

Compiler signifie que vous avez besoin du JAR pour compiler et exécuter l'application. Pour une application Web, par exemple, le JAR sera placé dans le répertoire WEB-INF / lib.

Fourni signifie que vous avez besoin du fichier JAR pour la compilation, mais au moment de l'exécution, il y a déjà un fichier JAR fourni par l'environnement, vous n'avez donc pas besoin qu'il soit fourni avec votre application. Pour une application Web, cela signifie que le fichier JAR ne sera pas placé dans le répertoire WEB-INF / lib.

Pour une application Web, si le serveur d'applications fournit déjà le fichier JAR (ou ses fonctionnalités), utilisez "fourni", sinon utilisez "compiler".

Voici la référence.

Owen Cao
la source
11
Vous ne répondez pas à la question du PO? ' Qu'est-ce que cela change dans l'utilisation de la compilation de portée maven et fourni lorsque l'artefact est construit en tant que JAR ? «Notez que l'auteur déclare explicitement qu'il connaît la différence lors de l'emballage comme la guerre.
Alberto
puis-je utiliser fourni si je fais référence à un autre JAR déployé sur le même serveur d'applications ??
Samy Omar
1
Donc, pour être clair, une dépendance fournie n'est pas ajoutée au chemin de classe lors de mvn exec:javason exécution, mais une dépendance compilée l'est.
Jamie
J'ai posé cette question - stackoverflow.com/questions/37360132/… Le problème a été résolu en changeant la portée de fourni à compiler. Mais je ne vois aucune différence entre le pot compilé avec la portée "fournie" et le pot compilé avec la portée "compiler". Pourriez-vous expliquer pourquoi?
Pavel_K
Lisez la première réponse: coderanch.com/t/502091/tools/difference-maven-compile-scope
NINCOMPOOP
22

Si vous prévoyez de générer un seul fichier JAR avec toutes ses dépendances (le xxxx-all.jar typique), alors la portée est importante, car les classes à l'intérieur de cette portée ne seront pas incluses dans le JAR résultant.

Voir maven-assembly-plugin pour plus d'informations

jfcorugedo
la source
7
à condition que la dépendance ==> la dépendance ne soit PAS conditionnée.
Gab 是 好人
3
La confusion OP est clairement résolue lors de votre package maven-assembly-plugin, intéressant que les réponses les plus votées ne le mentionnent pas.
Henrique G. Abreu
Je ne comprends pas cette réponse. Cela ressemble plus à un commentaire.
reinierpost
11
  • compiler

Rendez disponible dans le chemin de classe, n'ajoutez pas cette dépendance dans le pot final s'il s'agit d'un pot normal; mais ajoutez ce pot dans le pot si le pot final est un seul pot (par exemple, un pot exécutable)

  • à condition de

La dépendance sera disponible dans l'environnement d'exécution, n'ajoutez donc pas cette dépendance dans tous les cas; même pas dans un seul pot (c'est-à-dire un pot exécutable, etc.)

Vijay
la source
3

Pour un fichier jar, la différence réside dans le chemin de classe répertorié dans le fichier MANIFEST.MF inclus dans le jar si addClassPath est défini sur true dans la configuration maven-jar-plugin. les dépendances «compiler» apparaîtront dans le manifeste, les dépendances «fournies» ne le seront pas.

Une de mes bêtes noires est que ces deux mots devraient avoir le même temps. Soit compilé et fourni, soit compilé et fourni.

Meule
la source
0

Lorsque vous définissez maven scope comme provided, cela signifie que lorsque le plug-in s'exécute, la version des dépendances réelle utilisée dépend de la version d'Apache Maven que vous avez installée.

Vishwa Ratna
la source
0

Si le fichier jar est similaire au fichier jar Spring Boot exécutable, la portée de toutes les dépendances doit être compiled'inclure tous les fichiers jar.

Mais si le fichier jar est utilisé dans d'autres packages ou applications, il n'a pas besoin d'inclure toutes les dépendances dans le fichier jar car ces packages ou applications peuvent fournir d'autres dépendances elles-mêmes.

Ali
la source