1
votes

Portée Maven - fournie, mais dépendances spring-boot-starter-webflux incluses dans le fichier jar compilé. Pourquoi?

Je veux créer une bibliothèque de fichiers jar et ne pas inclure de dépendances, car elles seront dans le chemin de classe de l'application qui utilisera cette bibliothèque. J'utilise maven scope - à condition pour cela et toutes les dépendances sont exclues mais il en reste peu. J'ai trouvé qu'ils venaient de spring-boot-starter-webflux . Pourquoi ça? Et que dois-je faire pour m'en débarrasser?

Voici l'exemple de dépendance

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <scope>provided</scope>
</dependency>

Un exemple de projet avec cette seule dépendance est sur https://github.com/pavelmorozov/MavenProvidedTest/blob/master/pom.xml p >

Le fichier jar de projet compilé vide a une taille de plus de 5 mégaoctets.

Mise à jour Après la suggestion de JF Meier , j'ai essayé mvn dependency: tree et j'ai trouvé deux bibliothèques avec une portée compile

<dependencyManagement>
    <dependencies>
        ...
        <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-reactor-netty</artifactId>
           <version>2.1.3.RELEASE</version>
       </dependency>
       ...
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-bom</artifactId>
            <version>${reactor-bom.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
       ...
    </dependencies>
</dependencyManagement>

Et par exemple je vois l'un des fichiers POM

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
    <version>2.1.3.RELEASE</version>
    <scope>provided</scope>
</dependency>

Maintenant, je ne comprends toujours pas pourquoi les autres bibliothèques incluses dans Spring Boot ne remplacent pas la portée pour compiler . Cela signifie-t-il que ces deux bibliothèques se construisent mal ou qu'elles construisent de cette façon pour une raison quelconque? Et je ne sais toujours pas comment supprimer de manière simple les dépendances qui semblent avoir une portée de substitution?

J'ai essayé de mettre le numéro de version dans ma dépendance POM - mais cela n'a aucun effet - les mêmes fichiers jar inclus dans le fichier jar du projet compilé:

  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-reactor-netty</artifactId>
  <version>2.1.3.RELEASE</version>
  ...
  <dependencies>
    <dependency>
      <groupId>io.projectreactor.netty</groupId>
      <artifactId>reactor-netty</artifactId>
      <version>0.8.5.RELEASE</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>

Mise à jour sur les parents

Le fichier pom parent spring-boot-starter-parent non contient n'importe quelle section dependencyManagement , mais a un autre parent - spring-boot-dependencies - et il a une section dependencyManagement , mais la portée compilée n'est pas à condition de. Cependant, certaines dépendances ont une importation de portée. Je ne comprends pas que ces dépendances à portée d'importation aient un effet dans mon cas. Quelques exemples d'ici:

[INFO]    +- org.springframework.boot:spring-boot-starter-reactor-netty:jar:2.1.3.RELEASE:provided
[INFO]    |  \- io.projectreactor.netty:reactor-netty:jar:0.8.5.RELEASE:compile
[INFO]    |     +- io.netty:netty-codec-http:jar:4.1.33.Final:compile
[INFO]    |     |  +- io.netty:netty-common:jar:4.1.33.Final:compile
[INFO]    |     |  +- io.netty:netty-buffer:jar:4.1.33.Final:compile
[INFO]    |     |  +- io.netty:netty-transport:jar:4.1.33.Final:compile
[INFO]    |     |  |  \- io.netty:netty-resolver:jar:4.1.33.Final:compile
[INFO]    |     |  \- io.netty:netty-codec:jar:4.1.33.Final:compile
[INFO]    |     +- io.netty:netty-codec-http2:jar:4.1.33.Final:compile
[INFO]    |     +- io.netty:netty-handler:jar:4.1.33.Final:compile
[INFO]    |     +- io.netty:netty-handler-proxy:jar:4.1.33.Final:compile
[INFO]    |     |  \- io.netty:netty-codec-socks:jar:4.1.33.Final:compile
[INFO]    |     \- io.netty:netty-transport-native-epoll:jar:linux-x86_64:4.1.33.Final:compile
[INFO]    |        \- io.netty:netty-transport-native-unix-common:jar:4.1.33.Final:compile
...
[INFO]    +- org.springframework:spring-webflux:jar:5.1.5.RELEASE:provided
[INFO]    |  \- io.projectreactor:reactor-core:jar:3.2.6.RELEASE:compile
[INFO]    |     \- org.reactivestreams:reactive-streams:jar:1.0.2:compile

La partie du contenu de spring-boot-starter-reacteur-netty que j'ai posté ici dans la mise à jour précédente. p>

Mettre à jour après la réponse de Andy Wilkinson juste pour clarifier - de telles dépendances ne sont pas incluses dans jar, il semble que le plugin Spring Boot maven fasse son travail de manière différente ici:

<dependencies>
    <!-- Nevertheless provided scope some jars from this dependency
     are in compiled jar file. Why ? -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
        <scope>provided</scope>
    </dependency>
</dependencies>


0 commentaires

3 Réponses :


1
votes

Il est possible que le pom parent ait une section dependencyManagement qui écrase les portées / versions.


6 commentaires

Bonjour. Merci pour votre idée. J'ai essayé de vérifier les fichiers pom des dépendances et mis à jour ma question. Je ne comprends toujours pas pourquoi la portée est remplacée dans quelques bibliothèques et comment y faire face.


Franchement, je ne comprends pas ce que tu as essayé (dans ta retouche). Ma suggestion était: Allez à spring-boot-starter-parent, qui est votre parent, et regardez s'il a une section . Regardez s'il définit certaines des dépendances qui sont "compilées" de manière inattendue au lieu de "fournies".


Bonjour. Oui, je fais probablement quelque chose d'étrange, car je ne comprends pas tout cela. Le parent n'a pas une telle section , mais il a un autre parent et une portée compilée là pas du tout utilisée. Cependant, certaines dépendances ont une importation de portée.


Les dépendances sans portée ont implicitement une portée de compilation. L'importation de l'étendue importe une liste à partir du fichier défini (recherchez donc les dépendances).


Malheureusement, je n'ai pas pu comprendre comment cela fonctionne et abandonner. Merci pour vos efforts.


Si vous ne trouvez pas les dépendances gênantes, vous pouvez toujours écraser la portée en listant les artefacts pertinents dans la section avec la portée souhaitée. Cela prend un certain temps, mais vous pouvez être sûr que votre dependencyManagement est plus fort que les définitions du POM parent.



2
votes

Un fat jar Spring Boot est destiné à contenir tout ce qui est nécessaire pour exécuter l'application. Vous ne pouvez pas utiliser -jar et -classpath en même temps lors du lancement de la JVM, cela signifie que le fichier jar doit contenir les dépendances fournies et qu'il n'y en a pas d'autre moyen pour eux d'accéder au chemin des classes.

Ce comportement est décrit dans le documentation pour le plug-in Maven de Spring Boot où il est dit:

L'exemple ci-dessus reconditionne un fichier jar ou war qui est construit pendant la phase de package du cycle de vie Maven, y compris toutes les dépendances fournies qui sont définies dans le projet.

Si vous ne voulez pas que le jar de votre application contienne des dépendances, c'est-à-dire que vous voulez que ce soit un bocal normal plutôt qu'un gros bocal, vous ne voulez probablement pas utiliser Maven de Spring Boot plugin pour le construire. Si vous le supprimez du fichier pom.xml de votre exemple de projet, puis que vous le construisez, le fichier jar résultant a le contenu suivant:

$ unzip -l target/MavenProvidedTest-0.0.1-SNAPSHOT.jar 
Archive:  target/MavenProvidedTest-0.0.1-SNAPSHOT.jar
  Length      Date    Time    Name
---------  ---------- -----   ----
      329  02-22-2019 11:33   META-INF/MANIFEST.MF
        0  02-22-2019 11:33   META-INF/
        0  02-22-2019 11:33   META-INF/maven/
        0  02-22-2019 11:33   META-INF/maven/io.spring/
        0  02-22-2019 11:33   META-INF/maven/io.spring/MavenProvidedTest/
        1  02-22-2019 11:33   application.properties
     1403  02-22-2019 11:33   META-INF/maven/io.spring/MavenProvidedTest/pom.xml
      101  02-22-2019 11:33   META-INF/maven/io.spring/MavenProvidedTest/pom.properties
---------                     -------
     1834                     8 files

Si vous le souhaitez certaines dépendances à inclure, mais pas toutes, vous pouvez continuer à utiliser le plug-in Maven de Spring Boot et exclut certaines dépendances à la place.


6 commentaires

Le lien vers la documentation est pour 2.1.3.RELEASE tandis que j'utilise 1.5.6.RELEASE avec MODULE . Je suis toujours sur java 8 et j'avais l'habitude d'avoir des jars de bibliothèque de cette façon. Cette disposition de module n'est pas dans la version 2.x (rappelez-vous que nous avons discuté de la mise à jour de la documentation avec vous). Le module de mise en page ne signifie pas jar exécutable - mais bibliothèque. Donc je n'ai pas du tout besoin de java -jar. De toute façon, je vais essayer votre idée de supprimer le plugin Spring Boot Maven.


Si vous avez besoin de la disposition du module, vous devez utiliser Spring Boot 1.5 partout plutôt que d'utiliser Spring Boot 2.1 et ne rétrograder que le plugin Maven. Pour mémoire, la documentation 1.5 décrit également le comportement avec les dépendances fournies .


Cela signifie que le plugin Spring Boot Maven 1.x n'est pas compatible avec Spring Boot 2.x. C'est nouveau pour moi - il me manque probablement quelque chose. Je travaille sur Spring Boot 2.x pendant un certain temps mais je n'ai pas réussi à trouver le moyen de créer une bibliothèque jar avec le plugin Spring Boot 2.x et de revenir au plugin 1.x (je suis toujours sur java 8). Voir également la mise à jour dans ma question - je viens d'essayer avec d'autres dépendances et elles ne sont pas incluses dans jar.


Je ne comprends pas pourquoi vous êtes toujours sur Java 8. Spring Boot 2.x prend en charge Java 8.


Comme je l'ai compris, la disposition du module a été supprimée dans le plugin maven 2.x de spring boot car les nouveaux java 9 ont des modules.


J'ai supprimé le plugin Spring Boot maven de tous les projets que je ne lance pas, et - les pots sont maintenant jolis et petits. J'ai essayé d'avoir une portée facultative et de ne pas avoir de portée du tout - cela semble n'avoir aucun effet. J'ai quitté Spring Boot maven plugin 2.x uniquement dans l'application dépendante - et celle-ci je vais l'exécuter. J'ai essayé et tout semble bien fonctionner. Merci pour votre aide! Bien que je ne comprenne toujours pas pourquoi spring-boot-starter-web n'inclut rien si la portée est fournie, mais certaines dépendances de spring-boot-starter-reacteur-netty sont incluses. Je ne peux pas aller plus loin car je passe déjà beaucoup de temps avec.



0
votes

D'après votre question, je comprends que vous avez besoin d'un petit fichier exécutable. Car vous pouvez utiliser le plugin spring-thin-launcher . Il exclura les dépendances à empaqueter dans le cadre du jar mais sera téléchargé à partir de maven lors de la première exécution ou vous pouvez fournir votre propre dépôt local où tous les fichiers jar peuvent être trouvés.

Pour plus de détails, reportez-vous à ce tutoriel


0 commentaires