Creating Executable Jars With Clojure

A Brief Overview

  1. Create the application directory structure.  For this example, I'm using org.etherplex.example.JarExample.  I'm going to make a project directory called simply "project".  I'm assuming Linux/OS X here, Windows users need to adjust this or install Cygwin.

    mkdir -p project/org/etherplex/example

  2. Create your application in Clojure, creating a main method that is named properly.  For this example, I used a file called JarExample.clj.  It resides in the project/org/etherplex/example folder.

    (in-ns 'org.etherplex.example)
    (clojure/refer 'clojure)
    (def JarExample-main (fn [& args] (println "This is an example application!")))

    If we want to have our "main" class be called JarExample, then in clojure, we need to define a function called JarExample-main.  In general, Clojure will look for methods of a class in the same package as that class, and will use the form TheClass-methodName to locate the proper class.
  3. Now we need to create a stubbed .class file that will dispatch method calls to our Clojure file.  The easiest way to do this is to use the REPL.  I start the REPL in the directory that is the parent of my project directory.  In this case, that's my home directory.

    cd ~
    java -jar path/to/clojure.jar

    Now that we are in a Clojure REPL, we can create our class stub:

    (gen-and-save-class "project" "org.etherplex.example.JarExample" :main true)

    First, we specify the path that contains our files ("project") and then the fully qualified class we want to create.  We also specify a flag that indicates that we want Clojure to create a main method that dispatches out to the Clojure file we created in Step 2.
  4. Unpack clojure.jar so you can include its contents in you jar file.  We need to make sure our jar has all the dependencies in it so it is easy to distribute.

    cd ~
    unzip path/to/clojure.jar
    mv clojure project
  5. Now we need to create a manifest file for the jar so Java know to execute JarExample.class.  This is the contents of a file called manifest.txt that I put in my project directory.

    Main-Class: org.etherplex.example.JarExample
    Class-Path: .

    It is vital that this file have a trailing newline!
  6. Finally, we can create our jar file:

    cd ~/project
    jar cmf manifest.txt myjar.jar clojure org

    And execute it with:

    java -jar myjar.jar

    This will create a jar file that contains clojure and your code, and will interpret/compile your .clj file on the fly and run it.  Good luck!
    Questions?  Email me at rpdillon <<at>> gmail <<dot>> com