问题
i created a sample polyglot program. i have a sensor and a robot implemented in java and AI implemented in clojure. and i can't connect maven properly
--src/main/java/clojuretest
|
DistanceSensor.java
AI.clj (uses DistanceSensor)
Robot.java (uses AI)
DistanceSensor.java:
package clojuretest;
public class DistanceSensor {
public int getValue() {return 5;}
}
AI.clj:
(ns clojuretest.AI
(:gen-class :methods [[isObstacleAhead [] boolean]]))
(defn -isObstacleAhead [this] (< (.getValue (clojuretest.DistanceSensor.)) 10))
Robot.java:
package clojuretest;
public class Robot {
public boolean shouldStop() {
return new AI().isObstacleAhead();
}
}
i can even manually force maven to compile it:
mvn clean clojure:compile
produces error - no DistanceSensor class (but for some reason creates AI.class). so then
mvn compile
sees AI.class and compiles everything correctly and tests pass. but what can i do to make mvn clean compile
pass? how should my pom.xml look like? also what can i do to make eclipse stop complaining about non existing AI.class?
回答1:
I think :gen-class
is usually a code smell, as is trying to instantiate such a class from Java code with new AI()
.
Here's an alternative approach that can solve this problem of cyclic dependencies:
- Define
AI
as a Java interface in your Java code - Write a Clojure function to create an instance conforming to the interface using
reify
- Dynamically invoke the Clojure function from Java (e.g. using the technique outlined in this blog post)
- You now have an instance of the AI interface that you can use however you like in Java
The advantage is this approach is that everything will work smoothly, in particular:
- The Java code base can be compiled independently of the Clojure code
- The Clojure code base can access all the defined Java classes and interfaces
- You don't need any special IDE / Maven config. In fact, you can treat is as just a regular Java app that happens to include
clojure.jar
as a dependency.
回答2:
You need to change layout of source code in your project. Clojure maven plugin requires, that clojure code went to separate directory, so you should have following layout:
src/
main/
java/
java-code
clojure/
clojure code
test/
java/
java tests code
clojure/
clojure tests code
More details you can find in following article
回答3:
You have an inter-dependency between Java code and Clojure code. No matter which type of classes you'll compile first, you'll get an error.
Since it's not an actual cyclic dependency, you can still fix this by splitting the Java compilation part in two.
First, compile DistanceSensor
, which doesn't depend on anything else.
Second, compile AI
, which depends on DistanceSensor
.
Finally, compile Robot
which depends on AI
.
To split the java compilation in two steps, you need to configure the default execution of the maven-compiler-plugin
so that it excludes Robot
, and add another execution after the clujure:compile
goal that excludes DistanceSensor
. You'll probably have to misuse the phases to properly order the three executions.
来源:https://stackoverflow.com/questions/14110657/java-mixed-with-clojure-in-maven-and-eclipse