Fork me on GitHub
#leiningen
<
2021-04-25
>
grazfather01:04:07

Hey guys, I am building an uberjar with lein and later trying to run it, but I am getting an issue with “Could not find or load main class”. How is the main class determined? I have one namespace, and my profile sets it for :main

Matti Uusitalo06:04:10

Can you post your project.clj

grazfather16:04:18

(defproject mal "0.1.0-SNAPSHOT"
  :description "x"
  :dependencies [[org.clojure/clojure "1.10.1"]
                 [net.n01se/clojure-jna "1.0.0"]]
  :repl-options {:init-ns mal.core}
  :profiles {:step0 {:main mal.step0-repl
                     :uberjar-name "step0_repl.jar"
                     :aot [mal.step0-repl]}})

mikerod01:04:14

You define your uberjar details in a custom profile

mikerod01:04:31

So you’d have to specify that lein with-profile step0 uberjar

mikerod01:04:43

Or use the built in automatically included profile :uberjar

grazfather13:04:51

I did invoke it that way

gklijs22:04:14

Do you have a '-main' function in that namespace?

grazfather22:04:37

and it runs as expected with lein with-profile step0 run

grazfather22:04:52

$ lein with-profile step0 run
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
user> test
user>$ lein with-profile step0 uberjar
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Compiling mal.step0-repl
Warning: The Main-Class specified does not exist within the jar. It may not be executable as expected. A gen-class directive may be missing in the namespace which contains the main method, or the namespace has not been AOT-compiled.
Created /Users/g/code/mal/impls/myclj/target/mal-0.0.1-SNAPSHOT.jar
Created /Users/g/code/mal/impls/myclj/target/step0_repl.jar
$ java -jar ./target/step0_repl.jar
Error: Could not find or load main class mal.step0_repl
Caused by: java.lang.ClassNotFoundException: mal.step0_repl

grazfather01:04:58

It’s because my ns didn’t have (:gen-class) in it.

👍 9
noisesmith17:04:31

consider that you can skip :gen-class or :aot, and use clojure.main as your entry point

grazfather16:04:43

Sorry, I don’t understand what you mean. Do you mean in my invocation of the jar? What would that look like?

noisesmith16:04:42

java -cp my.jar clojure.main -m my.ns

noisesmith16:04:12

an advantage here is that you can also run a repl (leave out the -m arg) and any number of namespaces can have a runnable -main

noisesmith16:04:45

(and you don't have a language feature that you use in prod but not during dev)

grazfather16:04:02

cool, I will want that, since each of my profiles have their own main. At work right now, but will try that out later. Thank you!

grazfather16:04:48

so is it that gen-class means turn a namespace into a java cjass, and i don’t need that if i get the clojure.main class to instead load/invoke the namespace?

💯 2
noisesmith16:04:49

this also works by having gen-class / -main in multiple namespaces, but I think just using clojure.main is simpler over all

noisesmith16:04:00

that's exactly it, cheers