java - 如何使用 Maven 将 Clojure 依赖项包含到 Java 项目中

标签 java maven clojure clojure-java-interop

我对 JVM 的所有东西都很陌生,想启动一个 Java 项目,该项目涉及 Clojure 库作为依赖项。我见过this question关于如何从 Java 运行 Clojure 代码,但是当我尝试在 mvn package 之后运行 jar 文件时, 我得到 cannot find symbolvariable Clojure .到目前为止,我的代码如下所示:

package org.example;

import clojure.java.api.Clojure;
import clojure.lang.IFn;

public class App 
{
    public static void main( String[] args )
    {

        IFn plus = Clojure.var("clojure.core", "+");
    }
}
到目前为止,我的 pom 文件如下所示:
<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.example</groupId>
  <artifactId>project</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>poi</name>
  <properties>
    <maven.compiler.source>1.6</maven.compiler.source>
    <maven.compiler.target>1.6</maven.compiler.target>
  </properties>
  <url>http://maven.apache.org</url>
  <repositories>
    <repository>
      <id>clojars</id>
      <url>https://repo.clojars.org/</url>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
      <releases>
        <enabled>true</enabled>
      </releases>
    </repository>
  </repositories>
  <build>
  <plugins>
    <plugin>
      <groupId>com.theoryinpractise</groupId>
      <artifactId>clojure-maven-plugin</artifactId>
      <version>1.8.3</version>
      <extensions>true</extensions>
    </plugin>
  </plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.clojure</groupId>
      <artifactId>clojure</artifactId>
      <version>1.10.1</version>
    </dependency>
    <dependency>
      <groupId>clj-python</groupId>
      <artifactId>libpython-clj</artifactId>
      <version>1.45</version>
    </dependency>
  </dependencies>
</project>
clojure-maven-plugin似乎下载了依赖项(我看到通常的下载在屏幕上飞),但在调用 Clojure 时仍然没有运气。导入后。
最后希望能引用libpython-clj从 Java 内部。
更新
我尝试了艾伦汤普森的答案,需要运行 lein pom得到一个 pom.xml 文件。然后我需要在项目级别将以下内容添加到 pom 中以将其添加到 mvn -q compile<properties> <maven.compiler.source>1.6</maven.compiler.source> <maven.compiler.target>1.6</maven.compiler.target> </properties>但是,在 mvn -q exec给了我很长的堆栈跟踪
[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.0.0:java (default-cli) on project demo: An exception occured while executing the Java class. example.Main -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.0.0:java (default-cli) on project demo: An exception occured while executing the Java class. example.Main
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:216)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:120)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:347)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:154)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:582)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:214)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:158)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: org.apache.maven.plugin.MojoExecutionException: An exception occured while executing the Java class. example.Main
    at org.codehaus.mojo.exec.ExecJavaMojo.execute(ExecJavaMojo.java:311)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:132)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
    ... 19 more
Caused by: java.lang.ClassNotFoundException: example.Main
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:246)
    at java.base/java.lang.Thread.run(Thread.java:834)
[ERROR]
[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/MojoExecutionException
更新 2
似乎正在运行 mvn clean install && java -jar target/<whatever-it's called>.jar当您将以下代码段添加到 <plugins> 中的 pom.xml 中时有效部分。
  <plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
      <archive>
        <manifest>
          <mainClass>demo.Main</mainClass>
        </manifest>
      </archive>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
    </configuration>
    <executions>
      <execution>
      <id>make-assembly</id>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
      </execution>
    </executions>
  </plugin>

最佳答案

介绍
我有一个使用 lein 的工作演示供您使用建立。对于 Maven 部分,示例项目在最后。

使用 lein build
文件:

~/expr/demo > ls -ldF  **/*.{java,clj}
-rwxr-xr-x  1 alanthompson  staff  904 Jul 24 13:25 project.clj*
-rw-r--r--  1 alanthompson  staff  130 Jul 24 13:24 src/clj/demo/core.clj
-rw-r--r--  1 alanthompson  staff  373 Jul 24 13:17 src/java/demo/Main.java
-rw-r--r--  1 alanthompson  staff  129 Jul 24 13:20 test/clj/tst/demo/core.clj
项目.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"]
                 [prismatic/schema "1.1.12"]
                 [tupelo "20.07.01"]]
    
  :profiles {:uberjar {:aot :all}}

  :global-vars {*warn-on-reflection* false}
  :main demo.core   ;  when use ^:skip-aot   ???

  :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" ]
)
Java源代码
package demo;
import clojure.java.api.*;
import clojure.lang.IFn;

public class Main {
  public static double add2(double x, double y) {
    return (x + y);
  }

  public static void main(String[] args) {
    System.out.println("java main - enter");
    IFn plus = Clojure.var("clojure.core", "+");
    plus.invoke(1, 2);
    System.out.println("java main - leave");
  }
}
Clojure 主
(ns demo.core
  (:use tupelo.core)
  (:gen-class))

(defn -main [& args]
  (println :clj-main-enter)
  (println :clj-main-leave))
Clojure 测试
(ns tst.demo.core
  (:use tupelo.core tupelo.test)
  (:import [demo Main])
  (:gen-class))

(dotest
  (spyx (Main/add2 2 3)))
Clojure 部分使用 lein 很简单:
~/expr/demo > lein clean; lein run
:clj-main-enter
:clj-main-leave

~/expr/demo > lein test

------------------------------------------
   Clojure 1.10.2-alpha1    Java 14.0.1
------------------------------------------

lein test tst.demo.core
(Main/add2 2 3) => 5.0

Ran 2 tests containing 0 assertions.
0 failures, 0 errors.
我们将使用 lein 来构建 uberjar:
~/expr/demo > lein uberjar
Compiling demo.core
Created /Users/alanthompson/expr/demo/target/uberjar/demo-0.1.0-SNAPSHOT.jar
Created /Users/alanthompson/expr/demo/target/uberjar/demo-0.1.0-SNAPSHOT-standalone.jar
然后使用 java -jar 运行任一 Clojure main或 Java 主要使用 java -cp
# Entrypoint controlled by `:main` key in `project.clj` => clojure `demo.main/-main` function
~/expr/demo > java -jar /Users/alanthompson/expr/demo/target/uberjar/demo-0.1.0-SNAPSHOT-standalone.jar
:clj-main-enter
:clj-main-leave

# ***** notice `demo.Main` Java class name *****
~/expr/demo > java \
  -cp /Users/alanthompson/expr/demo/target/uberjar/demo-0.1.0-SNAPSHOT-standalone.jar  \
  demo.Main   
java main - enter
java main - leave

更新
刚试过 Stuart Halloway 的 Clojure Maven example .
它会在 Java 14 上崩溃,所以要小心!
结果:
~/expr/demo/clojure-from-java > java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_252-b09)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.252-b09, mixed mode)

~/expr/demo/clojure-from-java > mvn  -q clean
~/expr/demo/clojure-from-java > mvn  -q compile
~/expr/demo/clojure-from-java > mvn  -q exec:java  -Dexec.mainClass=example.Main
fn says hello
file filter returns false
object toString returns <object created Fri Jul 24 13:55:11 PDT 2020>

更新 #2
如果您更新 pom.xml,您可以修复 Java 14 的问题。输出 Java 1.8 功能。摘抄:
<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <!-- put your configurations here -->
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
    <sourceDirectory>src/java</sourceDirectory>
    <resources>
        <resource>
            <directory>src/clojure</directory>
        </resource>
    </resources>
</build>
重要的部分是添加 1.8这里:
<source>1.8</source>
<target>1.8</target>
享受!

关于java - 如何使用 Maven 将 Clojure 依赖项包含到 Java 项目中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63080434/

相关文章:

java - 此 jdbc 资源是否已关闭?

eclipse - 如何使用 ANTLR4 和 Maven 自动生成词法分析器+解析器?

clojure - 如何在 clojure 中得到 "def"而不重新加载?

java - 将 HotswapAgent/DCEVM 与 Clojure REPL 结合使用时出现 LinkageError

java - 为什么它不要求我输入?

java - Swing JPanel.add 不会将组件添加到面板中

java - "Deleting"Maven中生成的默认jar

java - 构建 war 时删除 jar 文件的 Maven 插件

python - Python 的 KeyError 的惯用 Clojure 版本

Java - 解释gridbag权重显示像素关系/公式/转换