I am building a simple web app, which is dependent on a couple of pre-compiled jars and which I want to deploy on Heroku. I put the jars into a resources folder and added the following lines to my project.clj: 
:resource-paths ["resources/jsesh-6.5.5.jar"
                 "resources/jseshGlyphs-6.5.5.jar"
                 "resources/java-cup-11b-runtime.jar"
                 "resources/java-cup-11b.jar"
                 "resources/qenherkhopeshefUtils-6.5.5.jar"]
Now I am able to run the project using lein run -m hieroglyphs.web; however, when I compile everything with lein uberjar and try
java -cp ./target/hieroglyphs-standalone.jar clojure.main -m hieroglyphs.web
The program starts up, but then crashes with a java.lang.NoClassDefFoundError when it tries to access one of the classes defined in those jars:
java.lang.NoClassDefFoundError: jsesh/mdcDisplayer/preferences/DrawingSpecification
Should I do something extra so that classes defined in the jars are accessible after compilation?
All the code can be found here: https://github.com/macleginn/jsesh-web
Just having a resources directory doesn't help. You're going to need a proper local Maven repository. Luckily, making one isn't that hard.
Steps:
lib folder in your source repository:repositories {"local" "file:lib"} to your project.clj
mvn deploy:deploy-file -Dfile=resources/jsesh-6.5.5.jar -DartifactId=jsesh -Dversion=6.5.5 -DgroupId=jsesh -Dpackaging=jar -Durl=file:lib (that works for the jsesh jar). Note in particular the artifactId, groupId and version
:dependencies item for each jar. e.g. for the one I did in Step 4, [jsesh/jsesh "6.5.5"]
You'll need to commit the lib folder to source control, but can now delete the resources folder and the :resource-paths bit from project.clj
(Heavily based on notes from https://gist.github.com/stuartsierra/3062743)
You should change your java invocation to use the -jar option like so:
~/expr/rundir > java -jar ./calc-0.1.0-SNAPSHOT-standalone.jar 
main - enter
  (ac/add2 3 5) => 8
main - leave
for code that looks like this:
calc
├── project.clj
├── resources
│   └── adder.jar
└── src
    ├── calc
    │   └── core.clj
~/expr/calc > cat src/calc/core.clj 
(ns calc.core
  "Contains the core functions for namespace `calc.core`."
  (:require [adder.core :as ac] )
  (:gen-class))
(defn -main []
  (println "main - enter")
  (println (ac/add2 3 5))
  (println "main - leave"))
The file adder.jar was created using lein jar from another project with a single function:
(ns adder.core)
(defn add2 [x y]
  (+ x y))
The resulting file was renamed "adder.jar" and plopped into the resources dir of the calc project.  Looking at project.clj:
(defproject calc  "0.1.0-SNAPSHOT"
  :description    "FIXME: write description"
  :url            "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url  "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [
    [org.clojure/clojure "1.9.0"]
    [org.clojure/test.check "0.9.0"]
    [prismatic/schema "1.1.7"]
    [tupelo "0.9.71"]
  ]
  :profiles {:dev {:dependencies []
                   :plugins [
                     [com.jakemccrary/lein-test-refresh "0.22.0"] ] }
             :uberjar {:aot :all}}
  :global-vars {*warn-on-reflection* false}
  :main ^:skip-aot calc.core
  :source-paths       ["src"]
  :test-paths         ["src"]
  :resource-paths     ["resources/adder.jar"]
  :target-path        "target/%s"
  :jvm-opts           ["-Xms500m" "-Xmx2g"]
)
The trick is in the line for :resource-paths, like so:
:resource-paths     [ "resources/adder.jar" ]
You need to list each *.jar file separately as a string in the vector. Note that the following will not work:
:resource-paths     [ "resources" ]            ; does not find *.jar files
:resource-paths     [ "resources/*.jar" ]      ; wildcards do not work
:resource-paths     [  resources/adder.jar ]   ; without quotes fails
We can then create a uberjar for the calc project, which will include the stuff from adder.jar:
~/expr/calc > lein uberjar
Compiling _bootstrap
Compiling calc.core
Compiling tst.calc.core
Created /home/alan/expr/calc/target/uberjar/calc-0.1.0-SNAPSHOT.jar
Created /home/alan/expr/calc/target/uberjar/calc-0.1.0-SNAPSHOT-standalone.jar
You want to use the *-standalone.jar version for your uberjar.  We copy it to an empty dir to verify it works:
~/expr/calc > mkdir -p ../rundir
~/expr/calc > cp target/uberjar/calc-0.1.0-SNAPSHOT-standalone.jar ../rundir
~/expr/calc > cd ../rundir
~/expr/rundir > ls -al
total 11744
drwxrwxr-x 2 alan alan     4096 Jan 14 19:22 .
drwxrwxr-x 5 alan alan     4096 Jan 14 19:22 ..
-rw-rw-r-- 1 alan alan 12016027 Jan 14 19:30 calc-0.1.0-SNAPSHOT-standalone.jar
~/expr/rundir > java -jar calc-0.1.0-SNAPSHOT-standalone.jar 
main - enter
  (ac/add2 3 5) => 8
main - leave
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With