Clojure noob. I'm unable to get a basic example with :gen-class working.
$ lein new app pizza-parlor
; project.clj
(defproject pizza-parlor "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url "https://www.eclipse.org/legal/epl-2.0/"}
:dependencies [[org.clojure/clojure "1.10.1"]]
:main ^:skip-aot pizza-parlor.core
:target-path "target/%s"
:profiles {:uberjar {:aot :all
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})
; src/pizza_parlor/Deliverator.clj
(ns pizza-parlor.Deliverator
(:gen-class))
(defn -deliver [pizza]
(println "pipin' hot"))
$ lein repl
pizza-parlor.core=> (require 'pizza-parlor.Deliverator)
nil
pizza-parlor.core=> (def d (pizza-parlor.Deliverator.))
Syntax error (ClassNotFoundException) compiling new at (/tmp/form-init10318668819087633543.clj:1:1).
pizza-man.Deliverator
pizza-man.core=> (import pizza-parlor.Deliverator)
Execution error (ClassNotFoundException) at java.net.URLClassLoader/findClass (URLClassLoader.java:435).
pizza-parlor.Deliverator
I've tried the :aot option in project.clj and run lein compile to generate classes in target/default, but I get the same error.
What is the correct way to define a Java class via gen-class and then use it in the repl alongside the rest of my project code, or a test that I can run with lein test?
You are misunderstanding how to execute a function in the REPL.
You do not need to "create a class" in Clojure. Just start up a repl and invoke a function. There are several choices:
As the comment says, you only need the
(:gen-class)expression in thensform if you want to create an executable JAR file.Method 1: Switch to the desired namespace and run the function:
Method 2: Just invoke the function with a fully-qualified symbol:
This will only work with the "main" ns, identified by the expression
in
project.clj.Method 3: Require the namespace, then invoke the function with a fully-qualified symbol:
This will work for any namespace, even
demo.coreif the REPL places you in theusernamespace.Method #4: Build an executable uberjar
You must ensure that
(:gen-class)is present in the(ns ...)form AND that you have:main demo.corein yourproject.clj. ThenIf you see an error message like this:
then you forgot to include the
(:gen-class)in thensform.Look here for more details on gen-class.
Update
If you really want to create a Java class from within Clojure code, you need the function
gen-class, not thensexpression. See:Update #2
Do you really need to generate a Java class from Clojure code? It might be easier to just write a Java class in a
*.javasource code file. Leiningen is perfectly able to compile mixed Clojure & Java source code into a single executable. This might be the easiest way to go.