Executable .jar, with onejar-maven-plugin

Onejar-maven-plugin collects your application including dependencies, into one executable jar. It’s both easy and works well!

(UPDATED for version 1.3.0. See below.)

Problem

If you have ever tried doing this before with Maven, you have probably used maven-assembly-plugin, which would leave the door open for classpath problems!

It would extract all your dependency jars in one directory together with all your class files and all other classpath resources. The problem is that everything ended up in a big mix, with classpath resources possibly overwriting each other. For example, if two dependencies each had a log4j.properties file in their jar, one log4j.properties would overwrite the other.

No more of that mess!

Solution

Enter maven-onejar-plugin. It lets all your dependency jars stay jars, and your code is in its own jar. All of those jars are put in a bigger jar, which is made executable.

Configuration

It may sound weird, but it’s quite elegant! Just put this in your pom.xml‘s <plugins> tag to make it work:


    org.dstovall
    onejar-maven-plugin
    
        1.3.0
    
    
        
            
                
                    your.package.YourMainClass
                
            
            
                one-jar
            
        
    

You also need to add this to the pom:


    
        onejar-maven-plugin.googlecode.com
        http://onejar-maven-plugin.googlecode.com/svn/mavenrepo
    

Please note the new Maven repository URL. Me and onejar-maven-plugin founder Drew Stovall just recently moved the project to Google Code to make it more open and easier for others (like me!) to pitch in. Yesterday, I released version 1.2.3 of onejar-maven-plugin to our new Maven repo at Google Code. UPDATE: Just released version 1.3.0 with optional support for including and autoloading native libraries such as .dll files. (detailed usage instructions.)

Make sure you get the <pluginRepository> URL right so that the latest version will be available to you!

Use

Then do this to build everything:

mvn install

That will build both your normal jar, as well as another jar. You will get these:

Standalone one-jar.jar file, along with the original .jar file.
Standalone one-jar.jar file, along with the original .jar file.

myApp.one-jar.jar is the big executable that includes both myApp.jar, and all dependency jars.

You can run it standalone without any extra files, like this:

java -jar target/myApp.one-jar.jar

If you found this interesting, you might find my post about winstone-maven-plugin enlightning as well. It shows you how to make an executable .war file.

Credits

Thank you Drew Stovall for creating this Maven plugin in the first place, and thank you to the other contributors who have also submitted patches.

Project homepage: http://onejar-maven-plugin.googlecode.com

This Post Has 32 Comments

  1. Ulrik Sandberg

    If you run into problems when using onejar-maven-plugin in an annotation-based Spring project, chances are that it’s the classpath scanning that is the problem.

    I had the following setup:

    Class:

    package com.example;
    
    @Component("transformer")
    public class MyTransformer {
    

    Spring config:

    <context:component-scan base-package="com.example" />
    

    Bootstrapping code:

    	public static void main(String[] args) {
    		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    		MyTransformer transformer = (MyTransformer) context.getBean("transformer");
    		transformer.run();
    	}
    

    I got the following exception:

    NoSuchBeanDefinitionException: No bean named 'transformer' is defined
    

    I then switched to this config, still using annotation-based dependency autowire, but requiring an explicit bean definition:

    Spring config:

    <context:annotation-config />
    <bean id="transformer" class="com.example.MyTransformer" />
    
  2. Elisha

    Hi, I tried using the one-jar plugin with maven 2 but I keep on getting the following error message when I run mv install:

    Error message: Failed to resolve plugin for mojo binding: org.dstovall:onejar-maven-plugin:1.4.1:one-jar
    Root error message: Unable to download the artifact from any repository

    I added everything I should have using the example above. I don’t understand how I’m getting this error. Please help asap.

    1. Hugo Josefson

      @Elisha, thanks for your feedback!

      I tried the same thing too, and it Works For Me (TM).

      Please double-check the <pluginRepositories> and <pluginRepository> tags. If the error persists, please open an Issue at the onejar-maven-plugin project page, so we can help track down the problem. It will then help if you can attach your pom.xml to the issue.

      Project issue tracker: http://code.google.com/p/onejar-maven-plugin/issues/list

      /Hugo

  3. Elisha

    Hi Hugo,

    Everything seems to be working now. It seems that it was unable to add the plugin repository because I was accessing my repository on another machine. It is now fine. I seem to be having another issue though when I try and execute the jar. I will open an issue on this one at the onejar-maven-plugin project page.

    Elisha

  4. Stevo Slavic

    Just to confirm on what Ulrik wrote, component scanning doesn’t work with onejar. Not sure yet whom to blame.

  5. Kev

    Another confirmation that Spring component scanning doesn’t work with onejar. Bummer. Confirmation of Ulrik and Stevo’s findings.

  6. David

    Hi.

    I need your help.

    I have to include manually a jar-file into the one-jar file. I need to put this jar-file in the lib folder. How can I do it? The jar-file is an indirect dependency and the pluggin doesn’t include it automatically

    Thanks.

  7. David

    I want to do something like this:

    ${project.build.directory}/tmp/lib

    tools.jar

    the only thing that I want to change is the destiny folder into de one-jar file. I want to send “tolls.jar” into /lib. Exists any tag in the plugin to do this?

    Thanks.

  8. David

    Sorry for the last message…I want to write it:

    ${project.build.directory}/tmp/lib

    tools.jar

  9. David

    I’m sorry again. I’m fighting with this message…

    binlibs
    fileSet
    directory
    ${project.build.directory}/tmp/lib
    /directory
    includes
    include
    tools.jar
    /include
    /includes
    /fileSet
    /binlibs

  10. Susan

    I’m having trouble building. I get the error Unrecognised tag: ‘executions’ (position: START_TAG seen …rn

  11. Dawid

    Thanks Hugo for this post and the plugin. Great job !

  12. Lauri

    What if I don’t want the ‘one-jar’ in the jar name? Is there a way to define the jar name?

  13. Tonio

    Great wonderful, really love this for utility projects awsome.
    thanks a lot.

  14. JG

    Hi,
    I am using one jar plugin and I am able to get the jar compiled. However, the jars are nested. for example, I am trying to use org.acceleo.engine jar.

    The jar is inside the lib folder and inside the jar again I have the jar.
    During runtime, the application complains that it cannot find org.acceleo.engine.IModel class.

    I have a bunch of such jars to be included. Can you help me resolve this nested jar packaging issue.

    Best Regards,
    Jyothi

  15. Trishala

    I tried using above method to create executable with maven+testng and I am getting error – Exception in the thread “main” java.lang.class.exception.

  16. Erik Verheul

    The MANIFEST.MF file can not handle long path names as in this example:
    Manifest-Version: 1.0
    ImplementationVersion: 1.0
    Main-Class: com.simontuffs.onejar.Boot
    One-Jar-Main-Class: nl.verheulconsultants.switchispmaven.SwitchISPServ
    ice

    A CRLF is inserted in SwitchISPService which caused a problem for me.

    1. Chanseok Oh

      I’m using 1.4.4., and it works for me. Either it was fixed in recent versions, or your environment is different from mine.

  17. Dhonnee

    Thanks! Works like Eclipse -> Export -> Runnable JAR file

  18. Maret

    Hello! I’ve checked out much topics, but still don’t have the answer to my question:
    I have a name-conflict in library files (overwriting issue) and want to use one-jar plugin to pack my libraries together with my project jar in one big jar. But my project (framework) is not executable (has no ‘main’ class). When I make the one jar – everything looks fine (I do not define the main class at all). But when I load this jar to my another project it doesn’t see any of jars withing my big ‘one-jar’ package.
    Maybe you can help. Thanks

  19. James

    I am having an issue with installing and packaging my maven project, here is the output

    here is output from mvn install:
    [ERROR] Failed to execute goal org.dstovall:onejar-maven-plugin:1.4.4:one-jar (default) on project serpentscript: Execution default of goal org.dstovall:onejar-maven-plugin:1.4.4:one-jar failed: basedir C:\Users\James.Wierzba@exelisinc.com\workspace\serpentscript\target\dllextract does not exist -> [Help 1]

    here is output from mvn package
    [ERROR] Failed to execute goal org.dstovall:onejar-maven-plugin:1.4.4:one-jar (default) on project serpentscript: Execution default of goal org.dstovall:onejar-maven-plugin:1.4.4:one-jar failed: basedir C:\Users\James.Wierzba@exelisinc.com\workspace\serpentscript\target\dllextract does not exist -> [Help 1]

    Please assist me if you can

  20. Manolo

    I know this is an old post, but I just wanted to point out that there is something wrong with the markup here. It seems like you tried to write the version number and main class in bold font, and added “<strong>” tags. Unfortunately those tags show up in the xml code instead, so if someone doesn’t recognize that they might be confused when they copy&paste it and get an error from maven.

  21. Saurav Srivastav

    Hi,
    Thankyou for giving this best solution , but I configured the same configuration of OneJar in my pom file
    it is giving error : Failed to parse plugin descriptor for org.dstovall:onejar-maven-plugin:1.4.4 (/root/.m2/repository/org/dstovall/onejar-maven-plugin/1.4.4/onejar-maven-plugin-1.4.4.jar): error in opening zip file.

    When I try to hit the repsoitory URL it giving 404 error.
    as well as the jar file which has been downloaded in .m2 directory, that is not unzipping, I tried to check this jar file in jar decompier tool there also it is not opening, can any one help me here to get me correct repo URL or correct version of one jar plugin apart from 1.3.0 or 1.4.4

    1. Chanseok Oh

      This is an old post. Use 1.4.4 on Maven and do not put into pom.xml the repository configuration suggested in the post.

        1. ashah

          yes correct solution and perfect dependency url shared by Chanseok Oh

  22. ashah

    The one-jar plug-in had been hosted on google but has since been moved to the public maven. This was causing the build failure. so remove above provided configuration from your pom.xml files and add below dependency code in it.

    com.jolira
    onejar-maven-plugin
    1.4.4

  23. jr

    I’ve taken over an internal project that references a version 1.4.5 for one jar-maven-plugin. There is an existing jarfile, presumably built with that version. But my internet searches do not return any links, and, of course, the maven plugin site only knows about 1.4.4.
    Before I change my project to use 1.4.4, does anyone know anything about 1.4.5?

    Thanks!
    /s/jr

Leave a Reply