java - 使用 Maven 将 Clojure 和 Java 源代码打包成 JAR 文件
问题描述
我想在我的 Java 应用程序中使用 Clojure 代码:
; clj.clj
(ns utils
(:gen-class
:name clj.Clj
:methods [#^{:static true} [clj [] String]])
(defn -clj []
"Hello from Clojure!")
// Java.java
package main;
import clj.Clj;
public class Java {
public static void main(String[] args) {
System.out.println("Java main");
System.out.println(Clj.clj());
}
}
当我运行 JAR 文件时,我想要输出:
Java main
Hello from Clojure!
如何编译 Clojure 和 Java 文件并使用 Maven 将它们打包成可运行的 JAR 文件?
更新:
这是我拥有的当前代码:
<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.loadingbg</groupId>
<artifactId>proj</artifactId>
<version>1.0.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<!-- Clojure Compiler -->
<plugin>
<groupId>com.theoryinpractise</groupId>
<artifactId>clojure-maven-plugin</artifactId>
<version>1.8.4</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<namespaces>
<namespace>utils</namespace>
</namespaces>
<compileDeclaredNamespaceOnly>true</compileDeclaredNamespaceOnly>
<sourceDirectories>
<sourceDirectory>src/main/clojure</sourceDirectory>
</sourceDirectories>
</configuration>
</plugin>
<!-- Maven Compiler -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<!-- Maven Assembly Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>proj.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
<!-- Maven Shade Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<minimizeJar>true</minimizeJar>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>proj.Main</mainClass>
</transformer>
</transformers>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.clojure</groupId>
<artifactId>clojure</artifactId>
<version>1.10.0</version>
</dependency>
</dependencies>
</project>
; /src/main/clojure/utils.clj
(ns utils
(:gen-class
:name utils.Utils
:methods [#^{:static true} [clj [] String]]))
(defn -clj []
"Hello from clojure")
// /src/main/java/pack/Main.java
package proj;
import utils.Utils;
public class Main {
public static void main(String[] args) {
System.out.println("Starting");
System.out.println(Utils.clj());
}
}
我运行时得到以下信息mvn clean install
:
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.google.inject.internal.cglib.core.$ReflectUtils$1 (file:/usr/share/maven/lib/guice.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of com.google.inject.internal.cglib.core.$ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.github.loadingbg:bot >----------------------
[INFO] Building bot 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ bot ---
[INFO] Deleting /home/loadingbg/proj/target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ bot ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /home/loadingbg/proj/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ bot ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /home/loadingbg/proj/target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /home/loadingbg/proj/src/main/java/proj/Main.java:[3,13] package utils does not exist
[ERROR] /home/loadingbg/proj/src/main/java/proj/Main.java:[8,28] cannot find symbol
symbol: variable Utils
location: class proj.Main
[INFO] 2 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.136 s
[INFO] Finished at: 2020-12-22T22:36:42+02:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project
bot: Compilation failure: Compilation failure:
[ERROR] /home/loadingbg/proj/src/main/java/proj/Main.java:[3,13] package utils does not exist
[ERROR] /home/loadingbg/proj/src/main/java/proj/Main.java:[8,28] cannot find symbol
[ERROR] symbol: variable Utils
[ERROR] location: class proj.Main
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
它只是拒绝承认从 Clojure 文件生成的类。utils.clj
应该生成utils.Utils
具有Utils#clj()
返回字符串的静态方法的类。
我看到clojure-maven-plugin
上面的移动maven-compiler-plugin
会有所帮助,但它没有。关键是clojure-maven-plugin
要先执行,maven-compiler-plugin
但事实并非如此。如何重新排序插件执行顺序,这甚至有帮助吗?
更新 2(回应 Alan Thompson):
我复制了之前在新的 Leiningen 项目中的代码,但我收到了这个错误:
Compiling 1 source files to /home/loadingbg/proj/target/default/class-files
/home/loadingbg/proj/src/java/proj/Main.java:3: error: package utils does not exist
import utils.Utils;
^
/home/loadingbg/proj/src/java/proj/Main.java:8: error: cannot find symbol
System.out.println(Utils.clj());
^
symbol: variable Utils
location: class Main
2 errors
Compilation of Java sources(lein javac) failed.
我错过了什么吗?我复制了project.clj
.
解决方案
这个项目 展示了如何使用 Leiningen 轻松做到这一点。只需键入lein clean; lein jar
并选择要部署的 uberjar。
其中project.clj
包括详细信息:
(defproject demo "0.1.0-SNAPSHOT"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [
[org.clojure/clojure "1.10.2-alpha1"]
[org.clojure/spec.alpha "0.2.187"]
[prismatic/schema "1.1.12"]
[tupelo "20.08.27"]
]
:plugins [
[com.jakemccrary/lein-test-refresh "0.24.1"]
[lein-ancient "0.6.15"]
[lein-codox "0.10.7"]
]
:db "jdbc:postgresql://localhost/default"
:settings "settings-default.edn"
:profiles {:dev {:dependencies []}
:uberjar {:aot :all}}
:global-vars {*warn-on-reflection* false}
:main ^:skip-aot demo.core
:source-paths ["src/clj"]
:java-source-paths ["src/java"]
:test-paths ["test/clj"]
:target-path "target/%s"
:compile-path "%s/class-files"
:clean-targets [:target-path]
:jvm-opts ["-Xms500m" "-Xmx4g"]
)
确保您的代码符合预期的布局:
~/expr/demo > tree src
src
├── clj
│ └── demo
│ └── core.clj
└── java
└── demo
└── Calc.java
运行测试:
> lein clean ; lein test
Java HotSpot(TM) 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Java HotSpot(TM) 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Compiling 1 source files to /home/alan/expr/demo/target/default+test+test/class-files
lein test _bootstrap
-------------------------------
Clojure 1.10.1 Java 15
-------------------------------
lein test tst.demo.core
(demo.Calc/theAnswer) => 42
制作一个 uberjar:
> lein uberjar
Java HotSpot(TM) 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Compiling 1 source files to /home/alan/expr/demo/target/uberjar/class-files
Compiling demo.core
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, or the namespace has not been AOT-compiled.
Created /home/alan/expr/demo/target/uberjar/demo-0.1.0-SNAPSHOT.jar
Created /home/alan/expr/demo/target/uberjar/demo-0.1.0-SNAPSHOT-standalone.jar
单元测试甚至使用 Java 互操作:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(dotest
(is= 42 (spyx (demo.Calc/theAnswer))))
推荐阅读
- node.js - 赛普拉斯永远不会通过 Windows 上的加载屏幕
- sql - Redshift 中的每月计数行 - 如何在没有活动的月份的结果中包含 0 行
- python - 如何使用计数查找列的范围间隔并比较其值?
- reactjs - 使用 postgres PRN 堆栈在表格中格式化日期
- c - 带有共享测试问题目录的 Makefile
- javascript - 如何使用根节点项按顺序遍历嵌套 JSON
- rest - 如何在 odata 表达式中执行空值合并?
- javascript - 文字闪亮效果无法正常工作我该如何解决这个问题
- android - Android 应用看起来不像预览
- r - 从具有多行闪亮的模态中更改文本的字体大小