Peter Penzov Peter Penzov - 4 months ago 32
Java Question

Execute Jar file as standalone application

I want to execute jar file as standalone application. When I run the below command I get this error message:

[rcbandit@Laptop target]$ /opt/jdk1.8.0/bin/java -jar DX57DC-1.0.jar
no main manifest attribute, in DX57DC-1.0.jar
[rcbandit@Laptop target]$


This is the POM configuration:

<?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.dx57dc</groupId>
<artifactId>DX57DC</artifactId>
<version>1.0</version>
<packaging>jar</packaging>

<name>DX57DC</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mainClass></mainClass>
</properties>

<organization>
<name>Corporation Name</name>
</organization>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<excludeScope>system</excludeScope>
<excludeGroupIds>junit,org.mockito,org.hamcrest</excludeGroupIds>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.zenjava</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>2.0</version>
<configuration>
<mainClass>com.dx57dc.main.DX57DC</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>

</project>


I suppose that I'm missing a maven plugin. Can you tell me how I can fix this?

Answer

In order for a JAR file to be executable it needs to have a manifest file with Main-Class and Class-Path entries:

       <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>my.package.App</mainClass>               
                    </manifest>           
                </archive>
                <executions>
                    <execution>
                        <id>default-package</id>
                        <phase>package</phase>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </configuration>
        </plugin>

This produces a MANIFEST.MF file under META-INF directory in the root of your jar file. Only relevant entries listed:

Class-Path: lib/somejar.jar
Main-Class: my.package.App

The Class-Path states that in the directory where the jar file resides there exists a lib folder with file somejar.jar in it.

The Main-Class states that the file App.class exists in package my.package and its main method will be run.

update

If the lib folder isn't present the execution will fail when first dependent class is to be loaded. To evade this you can pack all the dependencies in your jar with the shade plugin:

       <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>my.package.App</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>

Since all the dependencies are packed together the Class-Path entry is not necessary any more.

Comments