I'm relatively new to the Maven mantra, but I'm trying to build a command-line runnable jar with Maven. I've setup my dependencies, but when I run mvn install and attempt to run the jar, two things happen. First, no main class is found, which is correctable. When I've corrected this, I get errors on run stating that classes cannot be found.
Maven is not packaging my dependency libraries inside of the jar, so I am unable to run the jar as a stand-alone application. How do I correct this?
The easiest way to do this would be to create an assembly using the maven-assembly-plugin and the predefined jar-with-dependencies descriptor. You'll also need to generate a manifest with a main-class entry for this uber jar. The snippet below shows how to configure the assembly plugin to do so:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
Then, to generate the assembly, just run:
mvn assembly:assembly
If you want to generate the assembly as part of your build, simply bind the assembly:single mojo to the package phase:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
And simply run:
mvn package
Maven is not packaging your dependencies inside your jar file, because you don't usually do this with Java programs.
Instead you deliver the dependencies together with your jar file and mention them in the Class-Path header of the Manifest.
To go this route, you'll need to enable the addClasspath property (documented here) for the maven-jar-plugin.
If you really want to include all your dependencies in your jar file, then you can use the Maven Assembly plugin to create a jar-with-dependencies.
This is what I would do for small projects. Most of the time you don't want one huge jar.
to build:
mvn clean dependency:copy-dependencies package
to execute (in target dir):
java -cp myjar.jar:./dependency/* com.something.MyClass
I Agree with Joachim Sauer,
Instead of using jar-with-dependency you should configure the jar plugin like that in your pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<index>true</index>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>[mainClassFullName]</mainClass>
</manifest>
<manifestEntries>
<mode>development</mode>
<url>${project.url}</url>
<key>value</key>
</manifestEntries>
</archive>
</configuration>
</plugin>
And use this assembly configuration to add the jar dependencies to you assembly:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>zip-with-jars</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>false</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</dependencySets>
</assembly>
Just add the below code in pom.xml and Run as: maven:install . The jar will be created in target folder of eclipse which can be used as "java -jar Hello.jar" . but make sure that name of main class is given com.abc.HelloWorld.java
<build>
<plugins>
<plugin>
<groupid>org.apache.maven.plugins</groupid>
<artifactid>maven-shade-plugin</artifactid>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalname>HelloW</finalname>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestentries>
<main-class>com.abc.HelloWorld.java</main-class>
<build-number>1</build-number>
</manifestentries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
I have a spring boot application, and the jar created by maven package can be run without setting up additional plugins.
Inside my pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.12</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
https://spring.io/projects/spring-boot
Related
I am trying to create jar for my spring boot server using spring boot maven plugin and my test automation framework jar from same project and pom file. To read external resources I am trying to defined manifest entries in maven jar plugin but this is causing spring server to not find application.properties in its default locations when run as a linux service using /etc/init.d/my-jar start.
Here is snippet of my pom file
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<descriptors>
<descriptor>src/assembly/dep.xml</descriptor>
</descriptors>
<archive>
<manifest>
<mainClass>com.myorg.mainclass</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.5.RELEASE</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<finalName>${project.artifactId}-${project.version}-main-only</finalName>
<archive>
<manifest>
<mainClass>com.myorg.mainclass</mainClass>
</manifest>
<manifestEntries>
<Class-Path>./config/</Class-Path>
</manifestEntries>
</archive>
<excludes>
<exclude>**/application-test.properties</exclude>
</excludes>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
I have tried changing phase of my maven assembly and jar plugin to verify but the problem still persists. Removing manifest entry seems to work but then my external resource files are not read.
To solve the problem I removed the manifest entries from maven jar plugin and then while running the test jar. I added the external resource directory path into classpath as follows:
java -classpath my/external/resource/directory/path -jar my-tests.jar
I have an application where Im using maven dependecies and Im also using an external jar of a project which is located in my computer, the project is added to the application manually. The problem is whenever I export the project with maven, It only exports all maven dependencies, not the externatl jar that I have included manually. Is there anyway that I can export it?
Here is my pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>
com.cristianruizblog.loginSecurity.LoginSecurityTutorialApplication
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Thanks for reading. If anyone can help I would be so happy!
As stated by #M. Deunum, try to get your external jar into a Maven repository to avoid enable any machine to build your jar. If this is no option, you can use the Maven system dependency scope to include the jar. Note that this is only a temporary solution as this scope has been marked as depricated.
I use Maven to build a JAR. When I check the JAR, I see a maven folder inside the META-INF folder. I want it to be excluded from the build. My current build code in the pom.xml looks like this:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>Libraries</classpathPrefix>
<mainClass>com.company.Main</mainClass>
</manifest>
<manifestEntries>
<Built-By>Me</Built-By>
</manifestEntries>
</archive>
<!-- <excludes>
<exclude>META-INF/maven/**</exclude>
</excludes> -->
</configuration>
</plugin>
<!-- ...more plugins... -->
</plugins>
</build>
I read that using the exclude tags allows you to exclude something but it doesn't work. Maybe this only refers to local files/folders? The maven folder is not part of the source, it's just added by Maven.
This answer kind of works but uses a different artifact hence a 2nd JAR is generated when I paste it into my pom.xml. I want to use my current build code and exclude the maven folder like described above. How can it be done using maven build rules?
The maven-jar-plugin uses the maven-archiver to handle packaging. It provides the configuration addMavenDescriptor, which is true by default. Setting it to false should remove the META-INF/maven directory.
...
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
....
</archive>
You can find the reference here.
You can use maven shade plugin to create the jar and exclude the maven folder using following configurations in you pom.xml file:
<profile>
<id>shade</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<excludes>
<exclude>META-INF/**</exclude>
</excludes>
</filter>
</filters>
</configuration>
</executions>
...
</profile>
I am trying to run a jar created by the maven shade plugin. I am configuring the main class the following way:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>org.comany.MainClass</Main-Class>
<Build-Number>123</Build-Number>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
...
But when I try running the jar using java -jar app.jar it gives the following error
"no main manifest attribute, in app.jar"
EDIT:
I checked the contents of the jar using jar tf app.jar and I see a MANIFEST.MF file. BUt it does not have the entry for main class. How do I make sure the manifest file in jar has this entry apart for adding it in the shade plugin configuration?
Maven's shade plugin uses the JAR generated by the jar plugin and adds dependencies on it. Since it seems like the transforms on the shade plugin do not work properly, you just need to set the configuration for the jar-plugin like so:
<build>
...
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.mypackage.MyClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
<plugin>
[Your shade plugin definition without the transformers here]
</plugin>
</build>
Don't forget to add shade as a target:
mvn clean package shade:shade
Check if you have more than one main(). If you do, maven needs to know which one to use.
I am having a similar problem to this question. I have tried all the suggestions listed and am still at a loss. My issue is that I am trying to build a maven project and distribute it to other machines, but the jar files are not being populated with a correct Manifest. Each time I build and run I get the following error: no main manifest attribute, in myjar.jar. Is there some sort of configuration file I need to edit? I just don't know what is going on. I have attempted this fix also, but to no avail.
You can add it into project's pom file, inside <project> tag:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<mainClass>your.main.class</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
Another option is to use the maven shade plugin. Unlike the maven jar plugin showed by tigran, the maven shade plugin includes your dependencies in the generated jar.
A sample usage of the plugin is :
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>your.main.Class</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>