Uberjar woes

662 views
Skip to first unread message

Tom Connors

unread,
Feb 27, 2014, 2:49:38 PM2/27/14
to clo...@googlegroups.com
Hi Everyone,
I've been having trouble creating an uberjar of a project and I'm hoping someone here can point me toward a solution.
After cleaning out the target directory (with "lein clean") and preprocessing my cljx, I can run the project with no trouble using lein repl and lein run. I can package up the project (lein with-profile prd uberjar) and get the resultant jar files. After that, the trouble starts. Running the jar (java -jar my-standalone.jar) fails with a NoClassDefFoundError error, pointing at a protocol defined in weaverjester's clout - clout/core/Route. I highly doubt clout actually has anything to do with the problem. After creating the uberjar, I can no longer run the project with lein run or lein repl - I get the same error, and I can't do anything with lein without getting that error until I remove the target directory.
I've inspected the jar and can see that it contains clout, but just clout/core.clj - no .class files. I edited clout's project.clj to include :aot :all, packaged it into a jar, replaced the clout jar in my local maven repo with that new jar, and re-packaged my project. At this point, when I ran the jar, I got another NoClassDefFoundError, this time pointing at another protocol, but this one from clojure.core: clojure/lang/ILookupHost.
I've been having this problem with the latest leiningen (2.3.4) and 2.2.0.
I've been futzing with my project.clj for some time, but to no avail. Any help greatly appreciated.
-Tom

Sam Ritchie

unread,
Feb 27, 2014, 5:45:22 PM2/27/14
to clo...@googlegroups.com
Hey Tom,

Can you post your project.clj for us to take a peek?

February 27, 2014 12:49 PM
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

--
Sam Ritchie (@sritchie)

Tom Connors

unread,
Feb 27, 2014, 5:56:27 PM2/27/14
to clo...@googlegroups.com
Hi Sam, thanks a lot for responding. Here's my project.clj: https://gist.github.com/tomconnors/9261413

Josh Lehman

unread,
Apr 11, 2014, 3:24:57 PM4/11/14
to clo...@googlegroups.com
Tom, 

Not sure if you every figured this out, but I'm having the same issue. In my case, the error points to the Lifecycle protocol in https://github.com/stuartsierra/component (com/stuartsierra/component/Lifecycle). 

It's a pretty barebones configuration. https://gist.github.com/jalehman/10494205

Tom Connors

unread,
Apr 11, 2014, 5:09:19 PM4/11/14
to clo...@googlegroups.com
Hi Josh,
My solution ended up being pretty lame: I stopped calling a function from clout, and the uberjar magically worked, as disappointing as that explanation is. As far as I could tell, the root cause of my problem was that clout depends on an old version of clojure (1.2, if I recall correctly) that defined a protocol that no longer exists in newer versions.
It doesn't look to me like you're getting the error for the same reason. Have you tried the standard things, like blow away the target directory and make sure you've required the ns before using its vars? How about.. and I hate this idea too... one by one, remove dependencies + code that uses them, and see if you can get a working jar? 
When you do manage to figure this out, please post back here, as I'd like to understand this error better (it sure is annoying, huh?).


On Thursday, February 27, 2014 2:49:38 PM UTC-5, Tom Connors wrote:

James Reeves

unread,
Apr 11, 2014, 5:18:27 PM4/11/14
to clo...@googlegroups.com
Clout doesn't depend on any protocols in Clojure. The only protocol it uses is defined within the clout.core namespace itself.

Problems like this are often caused by compiled class files on your classpath. Often they are in the target directory, which can be solved by a "lein clean". The :clean-non-project-files option being set to false in Josh's configuration looks very suspicious!

I've also had problems with class files being accidentally included in the jars of dependencies. In rare cases a dependency may contain class files from other projects, and because class files outrank clj source files, you end up with some pretty bizarre behaviour in such cases.

- James


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Josh Lehman

unread,
Apr 11, 2014, 11:44:02 PM4/11/14
to clo...@googlegroups.com, ja...@booleanknot.com
I've come up with a fix after lots of fiddling, and I cannot quite explain it -- but it works!

The component library involves creating records that implement the Lifecycle protocol. In every namespace where I implemented that protocol, I added a (:gen-class) to the namespace declaration. I also had a user namespace for development that used required the component library. I moved this into the project itself also: (ns user) -> (ns fmspider.user). Finally, I switched back and forth between having :clean-non-project-files set to true and false -- the only thing that worked was having it set to false. Every time I build, I always start with "lein clean" to be sure. 

Still not quite sure why it is that things worked this way, or if some other combination of the above would yield the same result.

Tom Connors

unread,
Apr 14, 2014, 9:38:07 AM4/14/14
to clo...@googlegroups.com
Thanks for that tip, James - I'll look through the jars of my dependencies for spurious classes and post back here if I find anything that might be of value to future reader of this thread.


On Thursday, February 27, 2014 2:49:38 PM UTC-5, Tom Connors wrote:

Fenton Travers

unread,
Sep 7, 2015, 9:49:44 AM9/7/15
to Clojure
I've had this problem too.  I solved in a slightly different way.  I had my main function in a clojure file that also defined a component.  I moved my main function into a different file and that did the trick.  I didn't need a :gen-class directive in each file that had a component.  I didn't need to bring my user.clj into my main source tree, I didn't need the :clean-non-project-files false directive either...just pulled the main function out of the file that also defined a component. 

Each time I did a

 lein clean; lein deps; lein compile; lein repl


  -or-
 
lein clean; lein deps; lein compile; lein uberjar



These are the directives I did use in my project.clj:

 
 :main example.core
 
:uberjar {:aot :all}
 
:aot [example.core]
 
:repl-options {:init-ns user}



Fenton Travers

unread,
Dec 10, 2015, 6:57:43 PM12/10/15
to Clojure
I hit this problem again and it had another solution.  I have included the ns: 'user' in my project.clj ala:

  :source-paths ["src" "dev"]

|-- dev
|   `-- user.clj
|-- project.clj
`-- src
    `-- mount_issue
        `-- core.clj

I required the library in the user.clj and that caused the havoc.  I have no idea why this happens.  I require the library in my normal src/... files and it isn't a problem.
Reply all
Reply to author
Forward
0 new messages