Can't build a jar using Leiningen - clojure

I'm trying to make a stand alone jar from my bare-bones Clojure project using the Leiningen plugin in Intellij's Cursive.
To create the project, I just created the project.clj file, opened it, and Cursive offered to import it as a project.
project.clj:
(defproject WaterTimer "1"
:description "A timer that reminds you to drink water"
:main tone-producer/main)
tone-producer.clj:
(ns tone-producer
(:require [general-helpers :as g])
(:import [javax.sound.midi MidiSystem
Synthesizer
MidiChannel])
(:gen-class))
(defn main [& args]
(println "Test!"))
When I run the "uberjar" task, I get the following output:
Warning: specified :main without including it in :aot.
Implicit AOT of :main will be removed in Leiningen 3.0.0.
If you only need AOT for your uberjar, consider adding :aot :all into your
:uberjar profile instead.
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.
Created C:\Users\slomi\IdeaProjects\WaterTimer\target\WaterTimer-1.jar
Created C:\Users\slomi\IdeaProjects\WaterTimer\target\WaterTimer-1-standalone.jar
I also tried changing the main function to have the default name, and omit the name from the defproject:
(defproject WaterTimer "1"
:description "A timer that reminds you to drink water"
:main tone-producer)
(ns tone-producer
(:require [general-helpers :as g])
(:import [javax.sound.midi MidiSystem
Synthesizer
MidiChannel])
(:gen-class))
(defn -main [& args]
(println "Test!"))
But now I get the error:
Error: Could not find or load main class clojure.main
Compilation failed: Subprocess failed
The structure is:
WaterTimer
src
tone-producer.clj
project.clj
target
Any guidance here would be appreciated.

After a bit of fiddling
I dropped (:require [general-helpers :as g]) since its not necessary to demostrate the issue
Error: Could not find or load main class clojure.main Compilation failed
you didn't include the clojure dependency [1]
:gen-class needs AOT - as Sanchayan pointed out
see [2]
project.clj
(defproject WaterTimer "0.0.1"
:description "A timer that reminds you to drink water"
:dependencies [[org.clojure/clojure "1.8.0"]] ;; <- [1]
:main tone-producer
:aot [tone-producer]) ;; <- [2]
src/tone_producer.clj - USE '_' instead of '-' in the filename
(ns tone-producer
(:import [javax.sound.midi MidiSystem
Synthesizer
MidiChannel])
(:gen-class))
(defn -main [& args]
(println "Test!"))
Result:
$ lein uberjar
Compiling tone-producer
Compiling tone-producer
Created .../watertimer/target/WaterTimer-0.0.1.jar
Created .../watertimer/target/WaterTimer-0.0.1-standalone.jar
$ java -jar target/WaterTimer-0.0.1-standalone.jar
Test!
Generally I'd recommend to init a project with lein new <name> via command line and the import it into Cursive/Other IDE of choice.

For creating uberjars, the project file should have the :aot keyword enabling ahead of time compilation.
Here is an output from my project.clj file.
(defproject jdbc "0.1.0-SNAPSHOT"
:description "JDBC Project"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/java.jdbc "0.6.1"]
[postgresql "9.3-1102.jdbc41"]
[com.mchange/c3p0 "0.9.5.2"]
[byte-streams "0.2.2"]]
:main jdbc.core
:aot [jdbc.core])
Note the :main and :aot entries. Also it needs to be -main as already stated by birdspider.

Related

How to get `lein-repl` to use `user` instead of `main` for development purposes

I'm trying to set up a development version and a production version of my application using leiningen via the project.clj.
How can I have both? Because I have to comment out the :main part of my project.clj in order to get access to the development version when I use lein repl.
So I am using stuartsierra/reloaded leiningen template which has a nice development environment.
It comes with no :main key and when I added one that's when I stopped getting the development version of my project.
Instead of seeing
user=>
When I type lein repl I end up seeing my main, which is in the jaribu namespace
io.wakamau.jaribu=> ;; my main
The solution that seems to work is to comment out the :main part of the project.clj.
(defproject io.wakamau/jaribu "0.1.0-SNAPSHOT"
:description "trying out pedestal and component"
:url "https://github.com/kevinmungai/jaribu"
:license {:name "TODO: Choose a license"
:url "http://choosealicense.com/"}
:dependencies [[org.clojure/clojure "1.10.0"]
[com.stuartsierra/component "0.3.2"]]
:profiles {:dev
{:dependencies [[org.clojure/tools.namespace 0.2.11"]
[com.stuartsierra/component.repl "0.2.0"]]
:source-paths ["dev"]}
:uberjar {:aot [io.wakamau.jaribu]}}
:main ^{:skip-aot true} io.wakamau.jaribu
:min-lein-version "2.0.0")
trying out
lein repl
results in:
io.wakamau.jaribu=>
when the :main is commented out:
(defproject io.wakamau/jaribu "0.1.0-SNAPSHOT"
...
;; :main ^{:skip-aot true} io.wakamau.jaribu
:min-lein-version "2.0.0")
the result is:
user=>
I have to admit that I don't know much about using leiningen.
You can specify :repl-options {:init-ns io.wakamau.jaribu=>} in project.clj. You can also specify constants for different environments in profiles.clj, e.g., :dev {:main io.wakamau.jaribu}. Also see How do I start the REPL in a user defined namespace?.

Why can't I require a Java library in my Clojure file?

I've gotten leiningen to find a library I have in a corporate Artifactory repository, and it seems to download it just fine, but when I open try to require it, running the code with lein run comes back with a FileNotFoundException.
My project file looks like this:
(defproject clj-test "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.8.0"]
[com.ourgroup/library "1.0.0"]]
:repositories [["releases" {:url "https://url-to-our-repo"
:username "username"
:password "password"}]]
:main ^:skip-aot clj-test.core
:target-path "target/%s"
:profiles {:uberjar {:aot :all}})
My single code file looks like this:
(ns clj-test.core
(:gen-class)
(:require [library :as lib]))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println "And now for something completely different..."))
You need to import a class. To get the name of the class take a look inside the jar (or at the Java source code) and find the Java package and class that make up the fully qualified class name that you need to import.
I've edited this. My earlier mistake has been corrected with the comment: "You require namespaces; you import classes. Requiring a class is no good". So for Java interop you need to import classes, the same as you would be doing if you were writing a Java source file.

Could not locate clojure/data/xml__init.class in a luminus project

In my luminus project I've added this:
[org.clojure/data.zip "0.1.2"]
to the list of dependencies but this throws an exception still:
(ns myapp.rss
(:use [clojure.data.xml :as xml :only [emit]]))
which is:
Could not locate clojure/data/xml__init.class or clojure/data/xml.clj on classpath
here is a working example to compare with:
project.clj:
(defproject hello "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:main hello.core
:dependencies [[org.clojure/clojure "1.7.0"]
[org.clojure/data.xml "0.0.8"]
[org.clojure/data.zip "0.1.2"]
[clj-http "2.2.0"]])
from core.clj:
(ns hello.core
(:require [clj-http.client :as http-client]
[clojure.zip :as zip]
[clojure.xml :as xml]
[clojure.data.xml :as xml-data :refer [emit]]
[clojure.data.zip.xml :as xml-z]))
(use ... :only) has been deprecated by the require :refer pattern.
And here are some common things to check:
you have actually fetched the dependencies since adding them to the project.clj file
Try running lein deps from the command line to make sure fetching the dependencies worked
restart cider (if in emacs)
try from lein repl
if none of this works look in ~/.m2/repository and make sure the class files are there
run ps -ef (if in linux) to look at the command used to start java and make sure the classpath contains your dependency.

Can't run uberjar with Leiningen 2.5.2

I was trying to pick up Clojure again, but am stumbling right at the beginning. I downloaded lein, and copied the following project.clj and a hello.clj to be absolutely sure that I have a minimal working example.
project.clj:
(defproject hello "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.7.0"]]
:uberjar {:aot :all}
:main hello.core
)
hello.clj:
(ns hello.core
(:gen-class)
)
(defn -main
"This should be pretty simple."
[]
(println "Hello, World!"))
When I run './lein uberjar' I get these warnings:
Warning: specified :main without including it in :aot.
Implicit AOT of :main will be removed in Leiningen 3.0.0.
If you only need AOT for your uberjar, consider adding :aot :all into your
:uberjar profile instead.
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.
Created .../target/hello-0.1.0-SNAPSHOT.jar
Created .../target/hello-0.1.0-SNAPSHOT-standalone.jar
Trying to run this either with ./lein run or with java -jar ./target/hello-0.1.0-SNAPSHOT-standalone.jar results in exceptions:
Can't find 'hello.core' as .class or .clj for lein run: please check the spelling.
Exception in thread "main" java.io.FileNotFoundException: Could not locate hello/core__init.class or hello/core.clj on classpath., compiling:(/private/var/folders/28/bk6d4xj123b0xvsvk91_1jg80009rn/T/form-init1007755193774766954.clj:1:125)
So what is my problem here?
:uberjar {:aot :all} -> :profiles {:uberjar {:aot :all}}
And move hello.clj into ./src/hello directory and rename it to core.clj

How do I fix this dependency issue in Clojure?

I'm having a lot of trouble fixing an issue where the dependencies for two different packages are colliding. My project.clj's dependencies look like this:
:dependencies [[org.clojure/clojure "1.6.0"]
[itsy "0.1.1"]
[amazonica "0.3.22" :exclusions [commons-logging org.apache.httpcomponents/httpclient com.fasterxml.jackson.core/jackson-core]]])
My namespace looks like this:
(ns crawler.core
(:require [itsy.core :refer :all])
(:require [itsy.extract :refer :all])
(:use [amazonica.core]
[amazonica.aws.s3]))
When I try to load the namespace into lein's repl with (load crawler/core), I get this error:
CompilerException java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonFactory.requiresPropertyOrdering()Z, compiling:(amazonica/core.clj:1:1)
Online sources suggest that this is a dependency mismatch. How do I fix it?
I put the exclusion on itsy rather than amazonica and it worked. Also fixed the NS form in core.clj.
project.clj:
(defproject blabla "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.6.0"]
[itsy "0.1.1" :exclusions [com.fasterxml.jackson.core/jackson-core]]
[amazonica "0.3.22" :exclusions [commons-logging org.apache.httpcomponents/httpclient]]])
core.clj:
(ns blabla.core
(:require [itsy.core :refer :all]
[itsy.extract :refer :all]
[amazonica.core :refer :all]
[amazonica.aws.s3 :refer :all]))
(defn foo
"I don't do a whole lot."
[x]
(println x "Hello, World!"))
to deal with these situatuions in general run
lein deps :tree
and add exclusions until only the newest versions remain.