web-dev-qa-db-fra.com

Générer un fichier jar dans Maven avec des dépendances et des tests

J'utilise ce code dans pom.xml pour créer un fichier jar.

   <plugin>
        <groupId>org.Apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
            <excludes>
                <exclude>**/log4j.properties</exclude>
            </excludes>
            <archive>
                <manifest>
                    <mainClass>test.LeanFTest</mainClass>
                </manifest>
            </archive>
        </configuration>
    </plugin>

J'ai un message d'erreur:

Échec du déploiement: l'élément de référentiel n'a pas été spécifié dans la distribution POM à l'intérieur

MISE À JOUR:

J'ai ajouté un autre plugin dans pom.xml.

        <plugin>
            <artifactId>maven-Assembly-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>test.LeanFTest</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
        </plugin>

Il génère un fichier jar, mais apparemment sans dépendances.

Exception dans le thread "principal" Java.lang.NoClassDefFoundError: org/Apache/log4j/Logger

Structure du projet:

C:.
├───.idea
│   └───libraries
├───META-INF
├───out
│   └───artifacts
│       └───Test_LeanFT_jar
├───resources
│   ├───leanftjar
│   └───META-INF
├───RunResults
│   └───Resources
│       ├───Snapshots
│       └───User
├───src
│   ├───main
│   │   ├───Java
│   │   │   ├───com
│   │   │   │   └───myproj
│   │   │   ├───jar
│   │   │   │   └───META-INF
│   │   │   ├───META-INF
│   │   │   ├───unittesting
│   │   │   └───utils
│   │   └───resources
│   └───test
│       └───Java
│           └───test
├───target
│   ├───classes
│   │   ├───com
│   │   │   └───myproj
│   │   ├───unittesting
│   │   └───utils
│   ├───generated-sources
│   │   └───annotations
│   ├───generated-test-sources
│   │   └───test-annotations
│   ├───maven-archiver
│   ├───maven-status
│   │   └───maven-compiler-plugin
│   │       ├───compile
│   │       │   └───default-compile
│   │       └───testCompile
│   │           └───default-testCompile
│   ├───surefire
│   ├───surefire-reports
│   │   ├───Command line suite
│   │   ├───junitreports
│   │   └───old
│   │       └───Command line suite
│   └───test-classes
│       └───test
└───test-output
    ├───All Test Suite
    ├───junitreports
    ├───My_Suite
    └───old
        ├───All Test Suite
        └───My_Suite

pom.xml fichier:

<?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>groupId</groupId>
    <artifactId>LeanFT</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>Mytest</name>
    <description>Regression test</description>

    <properties>
        <leanftsdk>C:/Program Files (x86)/HPE/Unified Functional Testing/SDK/Java/</leanftsdk>
        <maven.test.skip>true</maven.test.skip>
    </properties>

    <dependencies>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.14.3</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
            <version>1.3</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>com.hp.lft</groupId>
            <artifactId>sdk</artifactId>
            <version>14.0.0</version>
            <scope>system</scope>
            <systemPath>${leanftsdk}/com.hp.lft.sdk-standalone.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>com.hp.lft</groupId>
            <artifactId>report</artifactId>
            <version>14.0.0</version>
            <scope>system</scope>
            <systemPath>${leanftsdk}/com.hp.lft.report.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>com.hp.lft</groupId>
            <artifactId>unittesting</artifactId>
            <version>14.0.0</version>
            <scope>system</scope>
            <systemPath>${leanftsdk}/com.hp.lft.unittesting.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>com.hp.lft</groupId>
            <artifactId>verifications</artifactId>
            <version>14.0.0</version>
            <scope>system</scope>
            <systemPath>${leanftsdk}/com.hp.lft.verifications.jar</systemPath>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.Apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>1.10</version>
                <executions>
                    <execution>
                        <id>add-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>appmodels</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-Assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>test.LeanFTest</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.Apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
10
plaidshirt

Ma solution est de construire une archive (Zip ou autres formats) qui contient vos classes dans un pot, les pots de dépendances, un dossier avec des fichiers de configuration d'exécution et des scripts pour lancer l'application. La portée est d'avoir une application prête à fonctionner simplement en décompressant l'archive.

Le contenu de l'archive construite est:

artifactId-version.Zip:
<artifactId folder>
    ├─ config
    |    ├─ log4j2.xml
    ├─ lib
    |    ├─ <all dependencies jars>
    ├─ leanft.cmd
    ├─ leanft.sh
    └─ artifactId-version.jar

Vous devez adapter la solution en fonction de ce que/si vous avez besoin de fichiers de configuration. Vous n'avez pas besoin des dossiers META-INF avec les fichiers MANIFEST.MF car ils seront générés automatiquement par le plugin maven.

Structure du projet

<maven_module_root>
├─ src
|   ├─ main
|   |    ├─ Assembly
|   |    |    ├─ leanft-Assembly.xml
|   |    ├─ Java
|   |    |    ├─ <your classes content>
|   |    ├─ resources
|   |    |    ├─ log4j2.xml
|   |    |    ├─ <your runtime configuration files>
|   |    ├─ scripts
|   |    |    ├─ leanft.cmd
|   |    |    ├─ leanft.sh
│   └───test
├─ pom.xml

La structure du projet est similaire à votre structure actuelle avec deux dossiers supplémentaires:
- Assembly: dans ce dossier se trouve le leanft-Assembly.xml pour personnaliser le plug-in maven-Assembly.
- scripts: dans ce dossier sont les scripts de lancement de votre application. Cela est nécessaire si vous avez besoin de fichiers de configuration d'exécution disponibles pour modification. Dans mon exemple, les ressources/log4j2.xml seront dans un fichier de configuration afin que l'utilisateur puisse éditer ce fichier sans toucher à aucun bocal/archive.

Descripteur d'assemblage

La solution est basée sur le plugin maven Assembly avec une configuration personnalisée. Je vous recommande de vous familiariser avec, en commençant par le descripteur descripteur d'assemblage

Votre leanft-Assembly.xml pourrait ressembler à:

<Assembly
    xmlns="http://maven.Apache.org/plugins/maven-Assembly-plugin/Assembly/1.1.3"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.Apache.org/plugins/maven-Assembly-plugin/Assembly/1.1.3 http://maven.Apache.org/xsd/Assembly-1.1.3.xsd">
    <id>dist</id>
    <formats>
        <!-- <format>tar.gz</format> -->
        <format>Zip</format>
    </formats>
    <includeBaseDirectory>true</includeBaseDirectory>
    <baseDirectory>${project.artifactId}</baseDirectory>
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>${project.artifactId}-${project.version}.jar</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.build.directory}/lib</directory>
            <outputDirectory>/lib</outputDirectory>
            <includes>
                <include>*.*</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.build.outputDirectory}</directory>
            <outputDirectory>/config</outputDirectory>
            <includes>
                <include>log4j2.xml</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.basedir}/src/main/scripts</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>leanft.*</include>
            </includes>
        </fileSet>
    </fileSets>
</Assembly>

Maven pom

Enfin, le pom.xml utilise 3 plugins:

    <plugin>
        <groupId>org.Apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>3.0.1</version>
        <executions>
            <execution>
                <id>copy-dependencies</id>
                <phase>package</phase>
                <goals>
                    <goal>copy-dependencies</goal>
                </goals>
                <configuration>
                    <outputDirectory>${project.build.directory}/lib</outputDirectory>
                    <overWriteIfNewer>true</overWriteIfNewer>
                    <overWriteReleases>false</overWriteReleases>
                    <overWriteSnapshots>true</overWriteSnapshots>
                </configuration>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.Apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.0.2</version>
        <configuration>
            <archive>
                <manifest>
                    <addClasspath>true</addClasspath>
                    <classpathPrefix>lib/</classpathPrefix>
                    <mainClass>test.LeanFTest</mainClass>
                </manifest>
            </archive>
            <excludes>
                <exclude>log4j2.xml</exclude>
            </excludes>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.Apache.maven.plugins</groupId>
        <artifactId>maven-Assembly-plugin</artifactId>
        <version>3.0.0</version>
        <executions>
            <execution>
                <id>make-Assembly</id>
                <phase>package</phase>
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <finalName>${project.artifactId}-${project.version}</finalName>
            <appendAssemblyId>false</appendAssemblyId>
            <descriptors>
                <descriptor>src/main/Assembly/leanft-Assembly.xml</descriptor>
            </descriptors>
        </configuration>
    </plugin>

Je vais vous expliquer l'utilisation des plugins maven:
- maven-dependency-plugin: copiez toutes les dépendances à la phase de package dans un dossier lib sous le dossier cible.
- maven-jar-plugin:
- archive: générer le fichier manifeste, définir dans le manifeste toutes les dépendances du dossier lib et quelle est la classe principale afin que vous puissiez exécuter l'application également avec "Java -jar"
- exclut: n'incluez pas le fichier log4j2.xml dans le pot du module car il sera dans le dossier config disponible au moment de l'exécution à partir du pot extérieur.
- maven-Assembly-plugin: créez en phase de package un fichier Zip contenant votre distribution. L'archive est placée dans le dossier cible. La balise de descripteur référence votre fichier de configuration d'assemblage leanft-Assembly.xml.

Scénario

Le script pour lancer l'application appelle Java avec des paramètres prédéfinis, la ligne principale du script étant:

%Java_HOME%\bin\Java %JVM_ARGS% -cp %SCRIPT_DIR%\*;%SCRIPT_DIR%\config\ test.LeanFTest
5
catta

Vous devez spécifier la phase d'exécution dans le plugin maven-Assembly. Utilisez la configuration de maven-Assembly-plugin suivante.

     <plugin>
        <artifactId>maven-Assembly-plugin</artifactId>
        <configuration>
            <archive>
                <manifest>
                    <mainClass>test.LeanFTest</mainClass>
                </manifest>
            </archive>
            <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
        </configuration>
        <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
        </executions>
    </plugin>

Maintenant, lancez simplement mvn package sur le projet pom.xml (répertoire racine) et vous obtiendrez un jar entièrement assemblé par votre artifactId plus le suffixe "jar-with-dependencies".

3
Manmohan_singh

Pour créer un uber-jar (comme précisé dans les commentaires), on peut utiliser le plugin Maven Shade . Ce plugin va générer un JAR qui contient les classes de projet ainsi que toutes les classes des JAR de dépendance.

Remarque: Le plugin Maven Assembly avec le jar-with-dependencies Prédéfini générerait un uber-jar avec un classificateur fixe (jar-with-dependencies), À côté du jar non classifié. Il ne semble pas possible de le remplacer (autre que la définition d'un assembly personnalisé).

3
david a.