This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-09-27
Channels
- # announcements (2)
- # asami (25)
- # babashka (124)
- # beginners (46)
- # calva (55)
- # cljdoc (70)
- # clojure (68)
- # clojure-australia (2)
- # clojure-dev (63)
- # clojure-europe (38)
- # clojure-nl (1)
- # clojure-spec (1)
- # clojure-uk (8)
- # clojurescript (56)
- # community-development (4)
- # conjure (1)
- # copenhagen-clojurians (1)
- # core-async (1)
- # cursive (3)
- # datahike (5)
- # datomic (183)
- # depstar (2)
- # figwheel-main (10)
- # fulcro (20)
- # honeysql (2)
- # hyperfiddle (1)
- # integrant (68)
- # jobs (6)
- # jobs-discuss (5)
- # juxt (1)
- # malli (13)
- # off-topic (8)
- # pathom (2)
- # rdf (10)
- # reagent (11)
- # remote-jobs (1)
- # rum (1)
- # shadow-cljs (69)
- # spacemacs (1)
- # sql (5)
- # tools-build (51)
- # tools-deps (6)
- # xtdb (24)
Hello! I'm working in a monorepo and trying to uberjar our projects using tools.build
. I've gotten the uberjar compiling and built, but running it with java -jar
, I keep hitting a java.lang.ClassNotFoundException. Could not find or load main class monorepo.base.core
. I'm defining my main namespace in build.clj
and passing it to :main
in the uber
fn, the pom.xml
thats generated seems to be correct, and all the classes and files are present and correctly structured in target/classes
as needed for it to compile. Unpacking the jar after its built I've confirmed the -main namespace is present, but still it cant be found despite my best efforts. Is there something obvious I'm missing here? My only guess is creating a source pom.xml
that defines a main, to pass into write-pom
, as I dont see Main-Class
in the generated pom. But the attribute is obviously being set somewhere with the uber
fn when it builds. Here is my build.clj, pretty much straight from the tools.build
guide.
(ns build
(:require [clojure.tools.build.api :as b]))
(def lib 'monorepo/project)
(def main 'monorepo.base.namespace_with_mainfn)
(def version (format "1.2.%s" (b/git-count-revs nil)))
(def class-dir "target/classes")
(def basis (b/create-basis {:project "deps.edn"}))
(def uber-file (format "target/%s-%s-standalone.jar" (name lib) version))
(defn clean [_]
(b/delete {:path "target"}))
(defn prep [_]
(b/write-pom {:class-dir class-dir
:lib lib
:version version
:basis basis
:src-dirs ["src"]})
(b/copy-dir {:src-dirs ["../../bases/base" "."]
:target-dir class-dir}))
(defn uber [_]
(b/compile-clj {:basis basis
:src-dirs ["src" "resources"]
:class-dir class-dir})
(b/uber {:class-dir class-dir
:main main
:uber-file uber-file
:basis basis}))
the class not found is monorepo.base.core
- your main namespace is monorepo.base.namespace_with_mainfn
so those do not seem directly related
just going from the error, do you see monorepo.base.core in your uberjar?
re "I dont see `Main-Class` in the generated pom" - do you mean in the META-INF/MANIFEST.MF ?
the pom is not used by Java to do anything, so is irrelevant here
Apologies I mistyped, the error message is indeed with the defined monorepo.base.namespace_with_mainfn
. I do see monorepo.base.namespace_with_mainfn
in my uberjar after its built
a .class?
that is, the uberjar should have monorepo/base/namespace_with_mainfn.class in it
and inside META-INF/MANIFEST.MF ?
I dont have a MANIFEST.MF under my META-INF. contents is: META-INF/maven/monorepo/project/pom.xml and pom.properties
well something doesn't match up here. uber should always write a META-INF/MANIFEST.MF into the uber jar, and I don't know how it would be finding that class name otherwise
you won't see this in the target/classes dir, only in the uberjar
jar tf target/project-V-standalone.jar META-INF/MANIFEST.MF
should verify it exists
(whatever V you have)
oh sorry, yes inside the uberjar I have MANIFEST.MF and Main-Class is defined there correctly as monorepo.base.namespace_with_mainfn
well, then I don't understand the error. what's the exact command you're running?
can you dump the full output?
from the java command?
Its just this short one
Error: Could not find or load main class monorepo.base.namespace_with_mainfn
Caused by: java.lang.ClassNotFoundException: monorepo.base.namespace_with_mainfn
and you see jar tf target/project-standalone.jar monorepo/base/namespace_with_mainfn.class
?
waiting for it to uber again to see if this was the issue! It is there, but its under /classes/monorepo/base/namespace_with_mainfn.class , added classes in front of my main def in build.clj 🤞
Thinking I incorrectly assumed :class-dir
was ignoring/handling that. will update when it finishes
oh, well that's definitely not the right place, but that doesn't sound like the right fix
I don't understand how you're getting that from the script above
you should maybe clean target if you haven't been doing that, too
ahhh, yes finally finished
Error: Could not find or load main class classes.monorepo.project.namespace_with_mainfn
Caused by: java.lang.NoClassDefFoundError: monorepo/project/namespace_with_mainfn (wrong name: classes/monorepo/project/namespace_with_mainfn)
the wrong path is being included in the uber jar, but I don't understand how you're getting that with the script above.
hard for me to tell whether that is correct or not without knowing what the namespaces are
that is just the namespace, as its shown at the top of the file with my -main function.
yeah, so I don't think that is the wrong part
the wrong part is that you are getting a classes/ prefix dir included but I can't tell whether this class is coming from some other part of the monorepo via a local dep or from this part as you have not provided enough information
What's in ../../bases/base? What's in .? What's in target/classes after the copy? after the compile?
the write-pom is not needed and can be removed
what's in your deps.edn? are you using local/root deps?
This is a polylith monorepo, so the top level folder structure is
▾ workspace
▸ bases
▸ components
▸ development
▸ projects
Im in projects/thisProject
using the deps.edn there that defines thisProject's base, components, etc. So in the copy-dir
I go up 2 directories to the workspace, and back into bases/thisProjectsBase
to get all the actual src code. "."
is thisProject's folder that has the deps.edn and some other config files needed for compile. After the copy-dir
, target/classes
contains the folders from /bases/thisProjectsBase
which are /src /cljs /resources
, along with /node_modules /classes deps.edn shadow-cljs.edn
etc that are in thisProject's folderafter compile it looks the same. and the uberjar is built as expected under thisProject/target
that does seem suspicious, it doesn't seem like node_modules should have a classes subdir, but I don't know enough about node and can't see how that would end up effecting the uberjar
no they actually are two separate ones. target/classes
is where everything in the copy-dir
is going, and shouldnt affect much. thisProject
has a /classes
folder that contains all the dependencies from deps.edn, so when I copy-dir
"."
, which is my thisProject dir, it copies over /classes
as well into target/classes