Lein 无法将罐子添加到 uberjar
Lein fails to add jars to uberjar
我正在构建一个简单的 Web 应用程序,它依赖于几个预编译的 jar,我想将其部署在 Heroku 上。我将罐子放入 resources
文件夹并将以下行添加到我的 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"]
现在我可以 运行 使用 lein run -m hieroglyphs.web
的项目;但是,当我用 lein uberjar
编译所有内容并尝试
java -cp ./target/hieroglyphs-standalone.jar clojure.main -m hieroglyphs.web
程序启动,但随后在尝试访问这些 jars 中定义的 类 之一时崩溃并显示 java.lang.NoClassDefFoundError
:
java.lang.NoClassDefFoundError: jsesh/mdcDisplayer/preferences/DrawingSpecification
我是否应该做一些额外的事情,以便编译后可以访问 jars 中定义的 类?
所有代码都可以在这里找到:https://github.com/macleginn/jsesh-web
仅仅拥有一个资源目录并没有帮助。您将需要一个适当的本地 Maven 存储库。幸运的是,制作一个并不难。
步骤:
- Install Maven 如果需要
- 在源存储库中创建一个
lib
文件夹
- 将
:repositories {"local" "file:lib"}
添加到您的 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
的东西(适用于 jsesh jar)。请特别注意 artifactId
、groupId
和 version
- 为每个罐子添加适当的
:dependencies
项目。例如对于我在第 4 步中所做的那个,[jsesh/jsesh "6.5.5"]
- 为每个依赖项重复步骤 4 和 5
您需要将 lib
文件夹提交到源代码管理,但现在可以删除 resources
文件夹和 project.clj
[=25 中的 :resource-paths
位=]
(主要基于 https://gist.github.com/stuartsierra/3062743 的注释)
您应该更改 java
调用以使用 -jar
选项,如下所示:
~/expr/rundir > java -jar ./calc-0.1.0-SNAPSHOT-standalone.jar
main - enter
(ac/add2 3 5) => 8
main - leave
对于看起来像这样的代码:
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"))
文件 adder.jar
是使用来自另一个项目的 lein jar
创建的,具有单一功能:
(ns adder.core)
(defn add2 [x y]
(+ x y))
生成的文件已重命名为 "adder.jar" 并放入 calc
项目的 resources
目录中。查看 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"]
)
技巧就在 :resource-paths
的行中,像这样:
:resource-paths [ "resources/adder.jar" ]
您需要将每个 *.jar
文件单独列出 作为向量中的字符串 。请注意以下将不起作用:
:resource-paths [ "resources" ] ; does not find *.jar files
:resource-paths [ "resources/*.jar" ] ; wildcards do not work
:resource-paths [ resources/adder.jar ] ; without quotes fails
然后我们可以为 calc
项目创建一个 uberjar,其中将包含来自 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
您想为您的 uberjar 使用 *-standalone.jar
版本。我们将它复制到一个空目录以验证它是否有效:
~/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
我正在构建一个简单的 Web 应用程序,它依赖于几个预编译的 jar,我想将其部署在 Heroku 上。我将罐子放入 resources
文件夹并将以下行添加到我的 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"]
现在我可以 运行 使用 lein run -m hieroglyphs.web
的项目;但是,当我用 lein uberjar
编译所有内容并尝试
java -cp ./target/hieroglyphs-standalone.jar clojure.main -m hieroglyphs.web
程序启动,但随后在尝试访问这些 jars 中定义的 类 之一时崩溃并显示 java.lang.NoClassDefFoundError
:
java.lang.NoClassDefFoundError: jsesh/mdcDisplayer/preferences/DrawingSpecification
我是否应该做一些额外的事情,以便编译后可以访问 jars 中定义的 类?
所有代码都可以在这里找到:https://github.com/macleginn/jsesh-web
仅仅拥有一个资源目录并没有帮助。您将需要一个适当的本地 Maven 存储库。幸运的是,制作一个并不难。
步骤:
- Install Maven 如果需要
- 在源存储库中创建一个
lib
文件夹 - 将
:repositories {"local" "file:lib"}
添加到您的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
的东西(适用于 jsesh jar)。请特别注意artifactId
、groupId
和version
- 为每个罐子添加适当的
:dependencies
项目。例如对于我在第 4 步中所做的那个,[jsesh/jsesh "6.5.5"]
- 为每个依赖项重复步骤 4 和 5
您需要将 lib
文件夹提交到源代码管理,但现在可以删除 resources
文件夹和 project.clj
[=25 中的 :resource-paths
位=]
(主要基于 https://gist.github.com/stuartsierra/3062743 的注释)
您应该更改 java
调用以使用 -jar
选项,如下所示:
~/expr/rundir > java -jar ./calc-0.1.0-SNAPSHOT-standalone.jar
main - enter
(ac/add2 3 5) => 8
main - leave
对于看起来像这样的代码:
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"))
文件 adder.jar
是使用来自另一个项目的 lein jar
创建的,具有单一功能:
(ns adder.core)
(defn add2 [x y]
(+ x y))
生成的文件已重命名为 "adder.jar" 并放入 calc
项目的 resources
目录中。查看 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"]
)
技巧就在 :resource-paths
的行中,像这样:
:resource-paths [ "resources/adder.jar" ]
您需要将每个 *.jar
文件单独列出 作为向量中的字符串 。请注意以下将不起作用:
:resource-paths [ "resources" ] ; does not find *.jar files
:resource-paths [ "resources/*.jar" ] ; wildcards do not work
:resource-paths [ resources/adder.jar ] ; without quotes fails
然后我们可以为 calc
项目创建一个 uberjar,其中将包含来自 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
您想为您的 uberjar 使用 *-standalone.jar
版本。我们将它复制到一个空目录以验证它是否有效:
~/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