I have told gradle about my local jar file and it seems to be correctly placing it in my library. However, i want to invoke the clojure functions contained inside of it.
I’m able to use invoke clojure functions just fine: require.invoke(Clojure.read("clojure.core")
however i’m getting an error when i try to require the namespace of my library:
Could not locate fk_gen/core__init.class or fk_gen/core.clj on classpath. Please check that namespaces with dashes use underscores in the Clojure file name.
`
The error is really clear. But i’m not sure how to troubleshoot it. I assume i should
1. figure out the classpath my java ...process is looking at.
2. understand what determines the classpath of my functions inside my jar.
I understand abstractly what this all about, but the details seem to be eluding me.it sounds like you have the clojure jar on the classpath, but not the jar containing your code
a jar file is just a zip file, so you should be able to unzip the jar and see what files are inside it to verify if it contains your code or not
@hiredman that sounds right. the fact it doesn’t expand in my editor is troubling lol
it does contain my code. I’m probably doing something even more basic wrong.
what do you mean? does it contain a file fk_gen/core.clj
or a file fk_gen/core__init.class
?
And the namespace of your library is fk-gen.core
?
@hiredman
if I unzip that jar via jar xf fk-gen-0.3.3-alpha.jar
it expands to contain fk_gen/core.clj
@seancorfield (ns fk-gen.core...)
so yes. I believe thats a valid namespace?
And that JAR is on the classpath when you start your Java code? Or should I ask: how are you running your Java code?
@seancorfield I believe so, though as i said, i’m unsure of how to introspect my class path in different environments. I seem to be making progress as i pulled in the clj files for my library. Now its complaining that it can’t find the dependencies for my library 🙂.
Sounds like you didn't build your Clojure code JAR the right way?
Java doesn't like you taking shortcuts with dependencies (this is why "local JAR file" is a bad idea in nearly all cases).
@seancorfield thats possible. it occurs to me that this would need to be a uberjar (contain all the deps) for me to use it locally. But that seems to require a gen-class and a main function… which doesn’t make doesn’t make sense for a library. Do you have a suggestion on a workflow for when you want to interopt by calling clojure code from java? I tried to hit like the first 20 links and mostly got docs which didn’t seem specific answering my question of how to ‘easily’. I’m trying to rush this so I probably just need to back up and read that documentation
or maybe a uberjar doesn’t require a main entry point… i think the docs i’m reading just word things to imply it.
right, so importing the uberjar seems to be working. Which hopefully saves the demo i plan on doing tomorrow 🙂. I’ll go back and fill in the blanks later.
Uberjar does NOT require gen-class or AOT!
You can make an uberjar with zero AOT (well, except Clojure itself since that ships with part/all of it AOT'd, right?) and you can specify clojure.main
as the main entry point.
To play nice in the Java ecosystem as "just" a library JAR, you need to generate a POM with your dependencies, and have it in a Maven-like repo (or local .m2 cache) for other Java tools to use it easily.
So if you create a local JAR, you also need to create a pom.xml
, and then you could lein-localrepo
install it into .m2
(or put it in a Maven-like shared repo), when Gradle can just be pointed at that coordinate.
If your Clojure code uses libraries from Clojars, Gradle will also need to be told to look in Clojars (as well as Maven Central).
When we call Clojure from Java, we start the Java process with the classpath that Leiningen or Boot would use to run the Clojure code.