如何在不使用uberjar的情况下从新的lein app运行jar?

时间:2016-02-23 03:27:44

标签: jar clojure leiningen

我发现来自lein的新应用程序可以作为uberjar运行,但不能作为jar运行。是应该以这种方式工作,还是我的设置有问题?

$ lein new app feedme
$ cd feedme

Lein uberjar工作正常:

$ lein uberjar
Compiling feedme.core
Created .../feedme/target/uberjar+uberjar/feedme-0.1.0-SNAPSHOT.jar
Created .../feedme/target/uberjar/feedme-0.1.0-SNAPSHOT-standalone.jar

$ java -jar target/uberjar/feedme-0.1.0-SNAPSHOT-standalone.jar
Hello, World!

Lein jar失败了:

$ lein jar
Warning: The Main-Class specified does not exist within the jar. It may not be executable as expected. A gen-class directive may be missing in the namespace which contains the main method.
Created .../feedme/target/feedme-0.1.0-SNAPSHOT.jar
$ java -jar target/feedme-0.1.0-SNAPSHOT.jar 
Error: Could not find or load main class feedme.core

在core.clj的ns部分有一个:gen-class指令,所以我不确定问题是什么:

$ cat src/feedme/core.clj 
(ns feedme.core
  (:gen-class))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (println "Hello, World!"))

3 个答案:

答案 0 :(得分:4)

Lein jar只会将你自己的代码包装在一个jar中,例如它可以被另一个项目使用。它不包括任何依赖项(将在pom.xml中声明),包括clojure本身。如果没有有效的类运行(例如clojure.main),它就无法运行您的代码。下一个问题是你的require语句引用不在你的类路径上的工件中的定义(除非某些程序加载了你的pom.xml并知道如何实现这些依赖项。)

答案 1 :(得分:3)

在其MANIFEST.MF文件中查看任何jar(它们只是zip文件)。那个文件会告诉你主要的课程。因此,如果您确保MANIFEST.MF进入您的jar文件,它将是可自行运行的。 jar文件包含.class文件并引用其他jar文件 - 因此只要可以访问引用的jar文件,它就可以组成自己的类路径。

我刚看了几个jar文件。 MANIFEST.MF位于META-INF。这是一个示例内容:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.3
Created-By: 1.7.0_76-b13 (Oracle Corporation)
Main-Class: com.cmts.client.applic.upgrader.UsersGUI
Date-Created: 15/07/2015 02:23 AM
Class-Path: ../lib/config-1.2.1.jar          
            ../lib/scala-library-2.11.5.jar                      
            ../lib/org.springframework.beans-3.1.0.RC2.jar       
            ../lib/org.springframework.aop-3.1.0.RC2.jar

这个是由Ant创建的。我不知道列宁是否做同样的事情。但即使它没有,也没有理由你不能把META-INF\MANIFEST.MF放进罐子里。然后你将有一个自运行的jar文件。

稍后编辑 - lein清单示例:

:manifest {"Class-Path" "../lib/clojure-1.8.0.jar"}

答案 2 :(得分:2)

您得到Error: Could not find or load main class feedme.core因为jar不包含feedme / core.class文件。如果您运行jar -tf target/feedme-0.1.0-SNAPSHOT.jar,您将看到它根本不包含任何.class文件。 lein jar默认情况下不编译源代码。这是预期的行为:除非请求AOT编译,否则Clojure会动态编译代码。如果uberjar通过{:uberjar {:aot :all}}配置文件在project.clj文件中请求AOT编译 (您可以通过将uberjar配置文件更改为空{:uberjar {}}来进行小型实验,然后{ {1}}将导致完全相同的错误。)

您可以运行lein uberjar && java -jar target/uberjar/feedme-0.1.0-SNAPSHOT-standalone.jar来编译代码。但如果您运行lein with-profile uberjar jar,则会收到另一个错误:java -jar target/uberjar+uberjar/feedme-0.1.0-SNAPSHOT.jar。正如noisesmith java.lang.NoClassDefFoundError: clojure/lang/IFn指出的那样,它不包括任何依赖关系,包括Clojure本身。因此,您必须在类路径中明确指定Clojure:lein jar。这将打印Hello,World! (假设您的本地Maven仓库中有Clojure 1.8,您可能需要先获取它或更改路径/版本)。

如果没有编译,您可以使用java -cp "$HOME/.m2/repository/org/clojure/clojure/1.8.0/clojure-1.8.0.jar:target/uberjar+uberjar/feedme-0.1.0-SNAPSHOT.jar" feedme.core运行使用lein jar生成的jar(同样,您的Clojure jar的路径/版本可能会有所不同)。