Maven: compile a project using shade-plugin specifying main class and properties file

拈花ヽ惹草 提交于 2019-12-10 22:33:53

问题


New to Maven, I was trying to compile a project using Maven with maven-shade-plugin (as it seems the best plugin to build a fat jar out there). I tried to specify my main class to make a runnable jar file and some .properties files which contains translation strings.

Compilation and build seems passed, according to netbeans output, but I can't run it as following (assuming the jar built by Maven is renamed "program"):

/usr/bin/java -cp program.jar bot.Main
> could not find or load main class bot.Main

this is my project file structure:

and this is my 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>com.mycompany</groupId>
<artifactId>mavenproject1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<build>
    <resources>
    <resource>
        <directory>src/main/java/resources</directory>
        <includes>
            <include>**/*.properties</include>
        </includes>
    </resource>
</resources>
<plugins>

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>2.4.3</version>
    <configuration>
      <archive>
      <manifest>
        <addClasspath>true</addClasspath>
        <classpathPrefix>lib/</classpathPrefix>
        <mainClass>bot.Main</mainClass>
      </manifest>
    </archive>
    <shadedArtifactAttached>true</shadedArtifactAttached>
    <shadedClassifierName>launcher</shadedClassifierName>
    </configuration>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>shade</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

  <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>exec-maven-plugin</artifactId>
      <version>1.2.1</version>
      <executions>
          <execution>
              <goals>
                  <goal>java</goal>
              </goals>
          </execution>
      </executions>
      <configuration>
          <mainClass>bot.Main</mainClass>
      </configuration>
  </plugin>

</plugins>
</build>
<dependencies>
    <dependency>
        <groupId>org.telegram</groupId>
        <artifactId>telegrambots</artifactId>
        <version>2.4.0</version>
        <classifier>jar-with-dependencies</classifier>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.5</version>
    </dependency>
</dependencies>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>

Are resources included properly and why can't I run my program using java -jar command without specifying main class? It says me "invalid or corrupt jar file" which this should mean that is not runnable.

Also, why doesn't neither start specifying Main classpath?


回答1:


The issue is with your configuration of the Shade Plugin, which is currently

<configuration>
  <archive>
    <manifest>
      <addClasspath>true</addClasspath>
      <classpathPrefix>lib/</classpathPrefix>
      <mainClass>bot.Main</mainClass>
    </manifest>
  </archive>
  <shadedArtifactAttached>true</shadedArtifactAttached>
  <shadedClassifierName>launcher</shadedClassifierName>
</configuration>

There is no <archive> parameter to the shade goal. The fact that you're using a configuration element that is non-existent is not an error, the configuration will just be ignored, and this explains why your main class isn't being set in the Manifest.

To build an executable JAR with the Shade Plugin, you need to provide the ManifestResourceTransformer as a transformers. The correct configuration would be:

<configuration>
  <transformers>
    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
      <mainClass>bot.Main</mainClass>
    </transformer>
  </transformers>
  <shadedArtifactAttached>true</shadedArtifactAttached>
  <shadedClassifierName>launcher</shadedClassifierName>
</configuration>

Note that with this configuration, the shaded JAR will not replace the main JAR. shadedArtifactAttached is set to true, which means that the shaded JAR will be attached to the project as a secondary artifact. It will be distinguished from the main JAR with its classifier of launcher, i.e. the shadedClassifierName parameter.

After running mvn clean package on this project, you will then have 2 JARs created:

  • mavenproject1-1.0-SNAPSHOT.jar, which is the main JAR. This JAR only consists of the compiled Java sources of your application. It is not executable and does not contain all of the dependencies' classes in it.
  • mavenproject1-1.0-SNAPSHOT-launcher.jar is the shaded attached JAR, which was constructed by the Shade plugin. This one is executable and contains the dependencies' classes.

This means that if you want to launch your application as an executable JAR, you have to launch the -launcher.jar, and not the other one, with

java -jar mavenproject1-1.0-SNAPSHOT-launcher.jar

As a side-note, both JARs will contain your resources that are in <directory>src/main/java/resources</directory>, because they are resources of the project itself, as declared with the <resource> element. However, it would be preferable to respect the standard directory layout and place the resources in src/main/resources instead.



来源:https://stackoverflow.com/questions/40828881/maven-compile-a-project-using-shade-plugin-specifying-main-class-and-properties

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!