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