I've build this project with mvn clean install. Now I have a .jar file but I'm not able to use it with:
λ java -jar flyway-commandline-xxx.jar
no main manifest attribute, in flyway-commandline-xxx.jar
What am I missing?
An executable jar needs a "manifest file" - which is located at META-INF/MANIFEST.MF inside the jar.
You can use the Maven Assembly plugin to produce this manifest file in line with this:
...
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<configuration>
<archive>
<manifest>
<mainClass>dk.tbsalling.ais.cli.AisCli</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
...
The MainClass (referenced in the manifest file) is the class containing the main(...)-method called when you execute the jar.
You can have a look at https://github.com/tbsalling/aiscli/blob/master/pom.xml for a full, working example.
Use below 2 maven plugins in pom.xml:
maven-assembly-plugin with a goal to package all dependencies.
maven-jar-plugin along with this to add manifest and make jar with the dependencies included by assembly plugin.
Since, in assembly plugin below, appendAssemblyId is false, so final jar name will be with appname.jar only.
You can test assembly using command: "mvn clean compile assembly:single". (or using Jenkins JPaC file then add the command "clean compile assembly:single" under mavenGoals).
See below:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<finalName>appname</finalName>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.myorg.appname.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.myorg.appname.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
Related
I am trying to create a jar file of a java project. I am using eclipse IDE and maven to make the built. I am trying to execute it through command prompt
You need to use maven-assembly-plugin in your pom.xml if you are looking for an executable jar. Example:
<plugins>
<!-- other plugins -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>PATH_TO_YOUR_MAIN_CLASS</mainClass>
</manifest>
</archive>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Then build with maven: mvn clean install
Then you can run from command prompt: java -jar YOUR_JAR_NAME.jar
I create an executable jar with maven using the plugin
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>pack.Main</mainClass>
</manifest>
<manifestEntries>
<Class-Path>.</Class-Path>
</manifestEntries>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
I have all of the dependencies in the src/min/resources folder. After i build the jar, i unpack it with archive manager and i can see all of my dependencies at the root level.
Here is how i am trying to access a resource
ClassLoader classLoader = getClass().getClassLoader();
dataIn = new MarkableFileInputStreamFactory(
new File(classLoader.getResource("trainingData").getFile()));
This runs just fine in Eclipse. But when i try to run the executable jar file, i get
java -jar target/my-0.0.1-SNAPSHOT-jar-with-dependencies.jar -o 1
java.io.FileNotFoundException: File 'file:/path/to/myProject/target/my-0.0.1-SNAPSHOT-jar-with-dependencies.jar!/trainingData' cannot be found
why is JVM looking for File 'file:/path/to/myProject/target/my-0.0.1-SNAPSHOT-jar-with-dependencies.jar!/trainingData' ?
what can i do to solve this?
I was building a 'Maven module' project where there are 2 modules.
Module A
Module B
Module B is the one who uses Module A and when I run the Module B Main Class it runs perfect. But when I try to build a JAR from it, JAR includes invalid classpath jars in Manifest file.
Module B POM
<build>
<plugins>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.example.main.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Generated Manifest file
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: Someone
Class-Path: lib/com/example/a/1.0.0/module-a-1.0.0.jar lib/com/1stl
eg/jnativehook/2.0.2/jnativehook-2.0.2.jar lib/org/json/json/20160212
/json-20160212.jar lib/org/glassfish/jersey/core/jersey-client/2.22.2
/jersey-client-2.22.2.jar lib/javax/ws/rs/javax.ws.rs-api/2.0.1/javax
.ws.rs-api-2.0.1.jar lib/org/glassfish/jersey/core/jersey-common/2.22.......
As I see there is additional paths to the 'Class-Path'. How do I modify this to include only the jar name?
I'm executing 'mvn clean install'
If you do not want to edit your pom.xml, you can make the same with mvn package assembly:single
This command will also copy all of your dependencies into your .jar file.
I found a solution adding following plugin will include the required JARs to the single JAR
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<mainClass>com.example.main.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Your problem is that in any of your parent POMs the following has been configured <classpathLayoutType>repository</classpathLayoutType>. Remove it or override with simple.
After building a sample mvn project, I added my org.restlet dependencies & Java code.
Then, I successfully built my JAR via mvn install. Finally, I ran into an error when trying to run the JAR.
vagrant$ java -jar target/my-app-1.0-SNAPSHOT.jar
Failed to load Main-Class manifest attribute from
target/my-app-1.0-SNAPSHOT.jar
You need to set the main class in the manifest using the maven-jar-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.someclass.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
Taken from here.
EDIT
If you want to package the resulting jar with dependencies you can use this
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Taken from here.
If you dont have a manifest in your jar invoking java -jar will not work.
Use this command if you dont have a manifest:
java -cp foo.jar full.package.name.ClassName
I use maven assembly plugin to collect all dependencies into one jar file. How can I tell maven not to repack dependencies and include them as jar files into resulting jar?
Currently I use following plugin configuration.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<mainClass>package.Program</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
wanted structure of jar file:
my-jar-with-dependencies.jar
|-dependency1.jar
|-|-class1.class
|-dependency2.jar
|-|-class2.class
|-...........
and not
my-jar-with-dependencies.jar
|-class1.class
|-class2.class
|-.............
If I understand the question correctly you want to specify when the assembly plugn should be run or not. I this is the case you should consider creating a build profile and add the assembly plugin configuration to the new profile.
In pom.xml add:
<project>
...
<profiles>
<profile>
<id>myprofile</id>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<mainClass>package.Program</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
...
</project>
When you want maven to run the assembly plugin you can then use the -P switch to the 'mvn' script like this:
mvn -Pmyprofile clean package