如何生成一个包含所有Maven依赖项的可执行JAR文件?

huangapple go评论137阅读模式
英文:

How to produce an executable jar file with all maven dependencies?

问题

以下是翻译好的内容:

我有一个Maven项目,我想生成包含所有依赖项的JAR文件。
我使用 package shade插件 和命令 mvn package 来生成JAR文件。

然而,生成的JAR文件并没有考虑到pom.xml中的任何依赖项。生成的JAR文件一直给我异常:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Level

这是pom.xml的内容:

<dependencies>
    <dependency>
        <groupId>${project.groupId}</groupId>
        <artifactId>myProject-core</artifactId>
        <version>${project.version}</version>
    </dependency>
    <!-- 其他依赖项 ... -->
</dependencies>

<profiles>
    <profile>
        <id>client</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>${shade.version}</version>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>shade</goal>
                            </goals>
                            <configuration>
                                <!-- 配置信息 ... -->
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
                <!-- 其他插件 ... -->
            </plugins>
        </build>
    </profile>
</profiles>

我的错误在哪里?
甚至在运行JAR时也没有考虑到 &lt;mainClass&gt;myProject.package.main&lt;/mainClass&gt; 作为主类,我必须指定类名:

java -cp myApp.jar myProject.package.main

我查看了大部分问题,但没有解决我的问题。

英文:

I have a maven project and I would like to produce the jar file with all dependencies.
I use package shade plugin and the command mvn package to produce the jar file.

However, the produced jar file does not consider any of the dependencies that is pom.xml. The produced jar file keep give me exception:

Exception in thread &quot;main&quot; java.lang.NoClassDefFoundError: org/apache/log4j/Level

Here is the content of pom.xml:

&lt;dependencies&gt;
	&lt;dependency&gt;
		&lt;groupId&gt;${project.groupId}&lt;/groupId&gt;
		&lt;artifactId&gt;myProject-core&lt;/artifactId&gt;
		&lt;version&gt;${project.version}&lt;/version&gt;
	&lt;/dependency&gt;
	&lt;dependency&gt;
		&lt;groupId&gt;${project.groupId}&lt;/groupId&gt;
		&lt;artifactId&gt;myProject-parser&lt;/artifactId&gt;
		&lt;version&gt;${project.version}&lt;/version&gt;
	&lt;/dependency&gt;
	&lt;dependency&gt;
		&lt;groupId&gt;org.slf4j&lt;/groupId&gt;
		&lt;artifactId&gt;slf4j-log4j12&lt;/artifactId&gt;
		&lt;version&gt;${slf4j.version}&lt;/version&gt;
	&lt;/dependency&gt;
	&lt;dependency&gt;
		&lt;groupId&gt;info.picocli&lt;/groupId&gt;
		&lt;artifactId&gt;picocli&lt;/artifactId&gt;
		&lt;version&gt;${picoli.version}&lt;/version&gt;
	&lt;/dependency&gt;
	&lt;dependency&gt;
		&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
		&lt;artifactId&gt;maven-shade-plugin&lt;/artifactId&gt;
		&lt;version&gt;${shade.version}&lt;/version&gt;
	&lt;/dependency&gt;
	&lt;!-- https://mvnrepository.com/artifact/log4j/log4j --&gt;
	&lt;dependency&gt;
		&lt;groupId&gt;log4j&lt;/groupId&gt;
		&lt;artifactId&gt;log4j&lt;/artifactId&gt;
		&lt;version&gt;1.2.16&lt;/version&gt;
	&lt;/dependency&gt;
	&lt;dependency&gt;
		&lt;groupId&gt;org.apache.logging.log4j&lt;/groupId&gt;
		&lt;artifactId&gt;log4j-api&lt;/artifactId&gt;
		&lt;version&gt;2.13.1&lt;/version&gt;
	 &lt;/dependency&gt;
	&lt;dependency&gt;
		&lt;groupId&gt;org.apache.logging.log4j&lt;/groupId&gt;
		&lt;artifactId&gt;log4j-core&lt;/artifactId&gt;
		&lt;version&gt;2.13.1&lt;/version&gt;
 	 &lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;profiles&gt;
	&lt;profile&gt;
		&lt;id&gt;client&lt;/id&gt;
		&lt;build&gt;
			&lt;plugins&gt;
				&lt;plugin&gt;
					&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
					&lt;artifactId&gt;maven-shade-plugin&lt;/artifactId&gt;
					&lt;version&gt;${shade.version}&lt;/version&gt;
					&lt;executions&gt;
						&lt;execution&gt;
							&lt;phase&gt;package&lt;/phase&gt;
							&lt;goals&gt;
								&lt;goal&gt;shade&lt;/goal&gt;
							&lt;/goals&gt;
							&lt;configuration&gt;
								&lt;finalName&gt;myProject-client-${project.version}&lt;/finalName&gt;
								&lt;transformers&gt;
									&lt;transformer
										implementation=&quot;org.apache.maven.plugins.shade.resource.ManifestResourceTransformer&quot;&gt;
										&lt;mainClass&gt;myProject.package.main&lt;/mainClass&gt;
									&lt;/transformer&gt;
									&lt;transformer
										implementation=&quot;org.apache.maven.plugins.shade.resource.ServicesResourceTransformer&quot; /&gt;
								&lt;/transformers&gt;
								&lt;filters&gt;
									&lt;!-- This is necessary to avoid a java.lang.SecurityException --&gt;
									&lt;filter&gt;
										&lt;artifact&gt;*:*&lt;/artifact&gt;
										&lt;excludes&gt;
											&lt;exclude&gt;META-INF/*.SF&lt;/exclude&gt;
											&lt;exclude&gt;META-INF/*.DSA&lt;/exclude&gt;
											&lt;exclude&gt;META-INF/*.RSA&lt;/exclude&gt;
										&lt;/excludes&gt;
									&lt;/filter&gt;
								&lt;/filters&gt;
							&lt;/configuration&gt;
						&lt;/execution&gt;
					&lt;/executions&gt;
				&lt;/plugin&gt;
				&lt;plugin&gt;
					&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
					&lt;artifactId&gt;maven-jar-plugin&lt;/artifactId&gt;
					&lt;configuration&gt;
			 			 &lt;archive&gt;
							&lt;manifest&gt;
								&lt;!-- Jar file entry point --&gt;
								&lt;mainClass&gt;myProject.package.main&lt;/mainClass&gt;
							&lt;/manifest&gt;
			 			 &lt;/archive&gt;
					&lt;/configuration&gt;
				&lt;/plugin&gt;
									
			&lt;/plugins&gt;
		&lt;/build&gt;

Where is my mistake?
It is even does not consider &lt;mainClass&gt;myProject.package.main&lt;/mainClass&gt; for the main class when I run the jar I have to specify the class name:

java -cp myApp.jar myProject.package.main 

I looked over most of the questions and nothing solve my issue.

答案1

得分: 1

首先,有两个插件可以用来创建可执行的JAR文件:maven-shade-pluginmaven-assembly-plugin

它们之间的主要区别在于,maven-assembly 只是构建一个包含所有依赖项的JAR文件,而 maven-shade 还会在内部重定位这些依赖项,以便如果另一个项目依赖于您的JAR文件,您就不会冒与依赖项冲突的风险。

如果您不希望将此构件用作其他项目的依赖项,您可以使用 maven-assembly-plugin。以下是如何使用它的示例:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.1.1</version>
    <configuration>
        <finalName>${project.artifactId}</finalName>
        <archive>
            <manifest>
                <mainClass>myProject.package.main</mainClass>
            </manifest>
        </archive>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <appendAssemblyId>false</appendAssemblyId>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

如果您确实需要重定位依赖项,请尝试修改插件的清单配置,至少它应该解决您在识别主类方面遇到的问题:

<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
  <manifestEntries>
    <Main-Class>myProject.package.main</Main-Class>
    <X-Compile-Source-JDK>${maven.compiler.source}</X-Compile-Source-JDK>
    <X-Compile-Target-JDK>${maven.compiler.target}</X-Compile-Target-JDK>
  </manifestEntries>
</transformer>

希望这些信息对您有帮助。

英文:

First of all, there are two plugins that you can use to create fat jars: maven-shade-plugin and maven-assembly-plugin.

The main difference between them is that maven-assembly just builds a jar containing all the dependency, while maven-shade also relocate these dependencies internally so that, if another project is depending on your jar, you won't risk having conflicts on dependencies.

If you don't expect yo use this artifact as a dependency of other projects, you can use maven-assembly-plugin for it. Here is an example of how to use it:

        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-assembly-plugin&lt;/artifactId&gt;
            &lt;version&gt;3.1.1&lt;/version&gt;
            &lt;configuration&gt;
                &lt;finalName&gt;${project.artifactId}&lt;/finalName&gt;
                &lt;archive&gt;
                    &lt;manifest&gt;
                        &lt;mainClass&gt;myProject.package.main&lt;/mainClass&gt;
                    &lt;/manifest&gt;
                &lt;/archive&gt;
                &lt;descriptorRefs&gt;
                    &lt;descriptorRef&gt;jar-with-dependencies&lt;/descriptorRef&gt;
                &lt;/descriptorRefs&gt;
                &lt;appendAssemblyId&gt;false&lt;/appendAssemblyId&gt;
            &lt;/configuration&gt;
            &lt;executions&gt;
                &lt;execution&gt;
                    &lt;id&gt;make-assembly&lt;/id&gt;
                    &lt;phase&gt;package&lt;/phase&gt;
                    &lt;goals&gt;
                        &lt;goal&gt;single&lt;/goal&gt;
                    &lt;/goals&gt;
                &lt;/execution&gt;
            &lt;/executions&gt;
        &lt;/plugin&gt;

If you really need to shade your dependencies, try to modify the manifest config of the plugin with this, at least it should solve the problem that you-re having with identifying the main class:

            &lt;transformer implementation=&quot;org.apache.maven.plugins.shade.resource.ManifestResourceTransformer&quot;&gt;
              &lt;manifestEntries&gt;
                &lt;Main-Class&gt;myProject.package.main&lt;/Main-Class&gt;
                &lt;X-Compile-Source-JDK&gt;${maven.compiler.source}&lt;/X-Compile-Source-JDK&gt;
                &lt;X-Compile-Target-JDK&gt;${maven.compiler.target}&lt;/X-Compile-Target-JDK&gt;
              &lt;/manifestEntries&gt;
            &lt;/transformer&gt;

答案2

得分: 0

在依赖项中没有使用 org.apache.log4j 的 groupId,你有:org.apache.logging.log4j,但它与 org.apache.log4j 不同。

英文:

There are no groupId in the dependencies with org.apache.log4j, you have: org.apache.logging.log4j but its not the same as: org.apache.log4j

huangapple
  • 本文由 发表于 2020年4月8日 02:47:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/61087228.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定