问题
I use this code in pom.xml to create a jar file.
<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>
I got error message:
Deployment failed: repository element was not specified in the POM inside distribution
UPDATE:
I added another plugin in 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>
It generates a jar file, but seemly without dependencies.
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger
Structure of project:
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
file:
<?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>
回答1:
My solution is to build an archive (zip or other formats) that contains your classes in a jar, the dependencies jars, a folder with runtime configuration files and scripts to launch the application. The scope is to have a run ready application just by unzipping the archive.
The built archive content is:
artifactId-version.zip:
<artifactId folder>
├─ config
| ├─ log4j2.xml
├─ lib
| ├─ <all dependencies jars>
├─ leanft.cmd
├─ leanft.sh
└─ artifactId-version.jar
You should tailor the solution based on what/if you need configuration files. You don't need the META-INF folders with MANIFEST.MF files because will be generated automatically by maven plugin.
Project structure
<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
The project structure is similar with your current structure with two additional folders:
- assembly: in this folder is the leanft-assembly.xml to customize the maven-assembly-plugin.
- scripts: in this folder are the launcher scripts for your application. This is necessary it if you need to have runtime configuration files available for edit. In my example, the resources/log4j2.xml will be in a config file so the user can edit this file without touching any jar/archive.
Assembly descriptor
The solution is based on maven assembly plugin with custom configuration. I recommend to get familiar with it, starting with descriptor assembly descriptor
Your leanft-assembly.xml could look like:
<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
Finally, the pom.xml make use of 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>
I will explain the usage of maven plugins:
- maven-dependency-plugin: copy all dependencies at package phase in a lib folder under the target folder.
- maven-jar-plugin:
- archive: generate manifest file, define in manifest all dependencies from the lib folder and what is the main class so you can run the application also with "java -jar"
- excludes: don't include the log4j2.xml file in the module jar because will be in config folder available at runtime from outside jar.
- maven-assembly-plugin: create at package phase a zip file that contains your distribution. The archive is placed in target folder. The descriptor tag reference your assembly configuration file leanft-assembly.xml.
Script
The script to launch the application call java with predefined parameters, the main line from script being:
%JAVA_HOME%\bin\java %JVM_ARGS% -cp %SCRIPT_DIR%\*;%SCRIPT_DIR%\config\ test.LeanFTest
回答2:
You need to specify execution phase in the maven-assembly-plugin. Use the following maven-assembly-plugin configuration.
<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>
Now just run mvn package
on the project pom.xml (root directory) and you shall get a fully assembled jar by your artifactId plus "jar-with-dependencies" suffix.
回答3:
To create an uber-jar (as clarified in the comments), one may use the Maven Shade plugin. This plugin will generate a JAR that contains the project classes as well as all classes from the dependency JARs.
Note: Maven assembly plugin with the pre-defined jar-with-dependencies
would generate a uber-jar with a fixed classifier (jar-with-dependencies
), next to the unclassified jar. It does not seem possible to override it (other than defining a custom assembly).
来源:https://stackoverflow.com/questions/50508801/generate-jar-file-in-maven-with-dependencies-and-tests