I am using the maven assembly plugin to generate an app client that is included in an EAR.
However, it isn't including the Main Class for whatever reason. I can't figure out what is wrong.
My Maven Assembly plugin:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<id>my-program</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.program.my.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
The resulting MANIFEST.MF:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: me
Build-Jdk: 1.8.0_20
EDIT:
Here is the full Maven POM
Related
Given this plugin config in a Maven pom.xml:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>acme.Main</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
Why would MANIFEST.MF be missing Implementation-Version and Implementation-Title, given that all docs that I can get my hands on, either don't mention it, or imply its creation is a default?
The complete generated Manifest is:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven 3.8.6
Built-By: stewart
Build-Jdk: 17.0.5
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: acme.Main
Spring-Boot-Version: 2.7.5
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Apparently, behind the scenes, spring-boot-maven-plugin still relies on the Manifest created by maven-jar-plugin, because that's the base .jar that is being repackaged.
Having established that, we then find that
Starting with version 2.1, Maven Archiver no longer creates the
Implementation and Specification details in the manifest by default.
If you want them in your manifest you have to say so explicitly in
your configuration.
Thus, what is needed is to add the following to the pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
I use IntelliJ IDEA to generate a jar file with maven-assembly-plugin.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<mainClass>test.LeanFTest</mainClass>
</manifest>
</archive>
<finalName>${project.artifactId}-fatjar-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</plugin>
It didn't work, it asks continuously for dependencies during execution. I was unable to use jar file, so I imported the project to Eclipse and used the built-in jar export option. This jar is working fine. I couldn't find what the difference is between these jar files.
The reason is probably that Eclipse is generating a "Class-Path:" entry in the manifest file.
Try to update the assembly conf in your .pom file by adding something like (by heart, not checked):
<addClasspath>true</addClasspath>
By default the maven-assembly-plugin will not bundle all the dependencies required for your own jar to run standalone.
So you will need to add this below under the plugin configuration:
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
As a result, the plugin tag becomes:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<mainClass>test.LeanFTest</mainClass>
</manifest>
</archive>
<finalName>${project.artifactId}-fatjar-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef> <!-- the secret -->
</descriptorRefs>
</configuration>
</plugin>
You can run:
java -jar path/to/LeanFTest.jar
To directly run the program.
My pom.xml looks like this
...
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<archive>
<manifest>
<mainClass>application.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
...
but although I specified the main class, on clean package install maven only creates jars that aren't runnable.
How can I fix that? The manifest then looks like this:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: Matthias
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_121
Instead of maven compiler plugin, you should configure the maven jar plugin to create an executable jar :
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>application.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
To declare the source/target java version you could use :
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
instead of declaring the compiler plugin.
This is less verbose and it produces exactly the same result.
Besides, if you want to include dependency jars of your application inside your executable jar, you should favor the maven assembly plugin over the maven jar plugin :
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>application.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
I'm using maven-jar-plugin in pom.xml.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<!-- DO NOT include log4j.properties file in your Jar -->
<archive>
<manifest>
<!-- Jar file entry point -->
<addClasspath>true</addClasspath>
<mainClass>com.example.Manager</mainClass>
<classpathPrefix>dependency-jar/</classpathPrefix>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
I can see in logs that maven execute it:
[INFO] [jar:jar {execution: default-jar}]
[INFO] Building jar: example.jar
[INFO] [jar:jar {execution: jar}]
but it don't put main class to MANIFEST.MF:
Manifest-Version: 1.0
Built-By: romkazanova
Build-Jdk: 1.7.0_65
Created-By: Apache Maven
Archiver-Version: Plexus Archiver
i don't understand why. I work with Idea.
You have to define the configuration in a pluginManagement area cause the maven-jar-plugin is already bound to the build life-cycle
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.example.Manager</mainClass>
<classpathPrefix>dependency-jar/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
The problem you have is that the execution you have defined means to have a supplemental execution as the log output shows and not change the configuration of the existing execution within the life cycle.
Furthermore you seemed to be running on Maven 2 instead of Maven 3 and you should update as soon as possible because Maven 2 has been defined EoL
You can of course add the version of maven-jar-plugin.
Try to compile manually by prompt: mvn compile
or try: mvn clean install -Dmaven.test.skip=true
What IDE are you using?
#khmarbaise is wrong in his definition of PluginManagement. According to the definition in Maven documentation, PluginManagement is intended to configure project builds that inherit from this one. In your pom.xml you have no needs to keep the PluginManagement node.
You only have to change the location of your configuration node from execution level to plugin level. You can see that #khmarbaise did that too.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<configuration>
<!-- DO NOT include log4j.properties file in your Jar -->
<archive>
<manifest>
<!-- Jar file entry point -->
<addClasspath>true</addClasspath>
<mainClass>com.example.Manager</mainClass>
<classpathPrefix>dependency-jar/</classpathPrefix>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
Furthermore you don't have to keep the executions node anymore because maven-jar-plugin is already bound to the build life-cycle as #khmarbaise mentioned it.
I am trying to set my build server information into META-INF/MANIFEST.MF. It works very well when using maven-jar-plugin with manifestEntries . The problem is that when I am packaging the Jar with maven-assembly-plugin to a single Jar with dependencies (like in here: How can I create an executable JAR with dependencies using Maven?) I can't see my manifest entries anymore. My guess is that my MANIFEST.MF is being dropped, while the assembly runs, but I could not find the way to set it after the manifest completes.
This is how my pom.xml build section looks like:
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2</version>
<configuration>
<archive>
<manifest>
<mainClass>ConvertorMain</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-my-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<finalName>${project.artifactId}</finalName>
<archive>
<manifestEntries>
<Application-Version>${app.version.major}.${app.version.minor}.0</Application-Version>
<Built-By>${user}</Built-By>
<Git-Branch>${git.branch}</Git-Branch>
<Git-Commit>${git.commit}</Git-Commit>
</manifestEntries>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
</configuration>
</plugin>
</plugins>
...
</build>
Without the jar-with-dependencies, the MAINFEST.MF will contain:
Manifest-Version: 1.0
Git-Commit: 35ff1f997b0c01daf44ed23425a3dc93307faaf7
Build-Jdk: 1.7.0_03
Built-By: Build Server
Git-Branch: origin/HEAD
Created-By: Apache Maven
Application-Version: 0.2.57
Archiver-Version: Plexus Archiver
Then, unzip -q -c convertor-1.0-jar-with-dependencies.jar META-INF/MANIFEST.MF dumps:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: eranh
Build-Jdk: 1.6.0_35
Main-Class: ConvertorMain
You have simply to copy the archive section from your maven-jar-plugin configuration into the maven-assembly-plugin as well.