Fork me on GitHub
Drew Verlee20:05:04

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.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

Drew Verlee20:05:43

@hiredman that sounds right. the fact it doesn’t expand in my editor is troubling lol

Drew Verlee21:05:02

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?

Drew Verlee23:05:11

@hiredman if I unzip that jar via jar xf fk-gen-0.3.3-alpha.jarit 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?

Drew Verlee23:05:47

@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).

Drew Verlee23:05:51

@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

Drew Verlee23:05:13

or maybe a uberjar doesn’t require a main entry point… i think the docs i’m reading just word things to imply it.

Drew Verlee23:05:23

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.