How to make an executable jar using maven?

13,470

Solution 1

You can configure maven jar plugin to achieve this.

Try adding following just above dependencies section:

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
              <mainClass>com.mycompany.app.App</mainClass>
            </manifest>
          </archive>
        </configuration>
      </plugin>
    </plugins>
  </build>

Here, <addClasspath>true</addClasspath> will add classpath entries to the manifest of your jar, so as long as you have those jars in same directory, your application will run fine.

You can customize the library path with, for example, <classpathPrefix>lib/</classpathPrefix>. It means your libraries should be placed in relative /lib directory.

You can also use maven dependency plugin if you want to automatically copy your libraries to output directory.

Solution 2

Actually you'll just need to add

<packaging>jar</packaging>

to your header, In other words:

<?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">

  <parent>
    <groupId>com.host.domain</groupId>
    <artifactId>DataPlatform</artifactId>
    <version>4.2.8-RELEASE</version>
  </parent>

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>abc</artifactId>
  <version>1.0.0</version>
<!-- This is where the magic happens -->
  <packaging>jar</packaging>

Then when you invoke on the command line make sure you include the fully qualified name of your class, like this:

java -cp NameOfFile.jar com.mycompany.app.App

The advantage of this is that you can multiple class files with main() methods that can be executed in one .jar file.

You can also include the suggestion of @Amila so you don't have to include the name when executing the jar, but you'll have to use this syntax instead:

java -jar NameOfFile.jar

Share:
13,470
user1950349
Author by

user1950349

Updated on June 23, 2022

Comments

  • user1950349
    user1950349 almost 2 years

    My maven project is like this and I have a quartz.properties file in /src/main/resources folder as shown below

    my-app
    |-- pom.xml
    `-- src
        |-- main
        |   |-- java
        |   |   `-- com
        |   |       `-- mycompany
        |   |           `-- app
        |   |               `-- App.java
        |   `-- resources
        |       `-- quartz.properties
        `-- test
            |-- java
                `-- com
                    `-- mycompany
                        `-- app
                            `-- AppTest.java
    

    Now I want to make an executable jar using maven so that I can run it like this java -jar abc.jar. Below is my main method code which works fine in my laptop in my eclipse IDE but I want to run it on my ubuntu machine using java -jar command:

    public static void main(String[] args) {
        StdSchedulerFactory factory = new StdSchedulerFactory();
        try {
            factory.initialize(App.class.getClassLoader().getResourceAsStream("quartz.properties"));
            Scheduler scheduler = factory.getScheduler();
            scheduler.start();
        } catch (SchedulerException ex) {
            System.out.println("error= " + ExceptionUtils.getStackTrace(ex));
        }
    }
    

    And here is my pom.xml file as of now. What changes I need to have in my pom.xml file to make an executable jar so that I can run it with java -jar?

    <?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">
    
        <parent>
            <groupId>com.host.domain</groupId>
            <artifactId>DataPlatform</artifactId>
            <version>4.2.8-RELEASE</version>
        </parent>
    
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.mycompany.app</groupId>
        <artifactId>abc</artifactId>
        <version>1.0.0</version>
    
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz</artifactId>
                <version>2.2.1</version>
            </dependency>
            <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz-jobs</artifactId>
                <version>2.2.1</version>
            </dependency>
            <dependency>
                <groupId>javax.transaction</groupId>
                <artifactId>jta</artifactId>
                <version>1.1</version>
            </dependency>
            <dependency>
                <groupId>com.google.code.gson</groupId>
                <artifactId>gson</artifactId>
                <version>2.3.1</version>
            </dependency>
        </dependencies>
    </project>
    
  • user1950349
    user1950349 over 8 years
    Thanks. Do I need maven-dependency-plugin as well? I have dependency on various other libraries as well some open source and some internal.
  • user1950349
    user1950349 over 8 years
    something is weird, I tried your way and I did mvn clean install which generated a jar file and I used that file and ran it and I got this error java.lang.NoClassDefFoundError ----- Exception in thread "main" java.lang.NoClassDefFoundError: org/quartz/SchedulerException at java.lang.Class.getDeclaredMethods0(Native Method).
  • user1950349
    user1950349 over 8 years
    Only difference is - I also have maven-eclipse-plugin in my pom.xml file.
  • user1950349
    user1950349 over 8 years
    I do have a maven dependency for QuartzScheduler in my pom.xml.
  • user1950349
    user1950349 over 8 years
    May be this line is causing problem. I have something like this <classpathPrefix>dependency-jars/</classpathPrefix>
  • Amila
    Amila over 8 years
    that line means, you should place all your library jars in a subdirectory named "dependency-jars". have you done so?
  • user1950349
    user1950349 over 8 years
    I just added it but I am getting above error. I don't know why.
  • user1950349
    user1950349 over 8 years
    Do I need to use maven-shade-plugin here?
  • Amila
    Amila over 8 years
    No need to use shade plugin if your libraries are correctly located. Exact your jar and see MANIFEST.MF file has a line similar to: Class-Path: dependency-jars/lib1.jar dependency-jars/lib2.jar
  • user1950349
    user1950349 over 8 years
    Yes I do see that jar. I started using lib so I see this - lib/quartz-2.2.1.jar and lib/quartz-jobs-2.2.1.jar
  • Amila
    Amila over 8 years
    @user1950349 can you update your question with your output directory structure and the way you're executing your program?
  • user1950349
    user1950349 over 8 years