What is relationship between project.clj and dependent library jar files? - clojure

I am using lein 2.0
If a main application
(defproject rexfer "1.0.1-SNAPSHOT"
:description "Filters standard report from Patriot Properties' AssessPro."
:dependencies [[org.clojure/clojure "1.4.0"]
[org.clojure/tools.cli "0.2.2"]
[org.clojure/data.csv "0.1.2"]
[rexfer-csv "1.0.0-SNAPSHOT"]
[util "1.0.7-SNAPSHOT"]]
:omit-source true
:main rexfer.core)
depends on a library (util 1.07-SNAPSHOT)
(defproject util "1.0.7-SNAPSHOT"
:description "A general purpose Clojure library"
:dependencies [[org.clojure/clojure "1.4.0"]
[clojure-csv/clojure-csv "1.3.2"]
[org.clojure/data.csv "0.1.2"]]
:aot [util.core]
:omit-source true)
is the reference fetching a .jar file or a standalone .jar?
Another way to ask this question is should I be building standalone jars for libraries like
util "1.0.7-SNAPSHOT"
that require a main application to use them?

You should deploy the jar produced by lein jar rather than lein uberjar. You can also safely expect all reasonable libraries to be deployed in this way.
This is roughly because of the following:
correctly prepared jars contain metadata on their dependencies, so users will know to fetch the dependencies along with your jar;
it often happens that a project uses several libraries which share common dependencies -- it would be wasteful to have each shared dependency replicated in several jars;
the user may have good reason to override some of your dependency choices (which happens all the time, incidentally; replacing a transitive dependency with a different version or excluding a transitive dependency is common) -- with a regular jar they will be able to do so easily, while it would be a pain with an überjar.
Of course if the coordinates of some of your dependencies do happen to point at überjars, that's what's going to end up being pulled in by Leiningen. I've never come across a library misdeployed like that though.

If you don't want to run lein uberjar then the answer to your second question would be yes. These jars need to be available on the class path for the main application to run. The job of lein uberjar is to include all the dependencies and dependencies of dependencies etc.

Related

Can I force lein to ignore dependencies from any code external to current Clojure project?

I'm calling some Clojure (1.8) code in a larger Java project that I don't entirely have control over. Recently some code has been added to the parent that's causing conflicts with the HTTP client clj-http.
From my Clojure project, here's the output of lein deps :tree|grep http:
[clj-http "3.7.0"]
[org.apache.httpcomponents/httpasyncclient "4.1.3" :exclusions [[org.clojure/clojure]]]
[org.apache.httpcomponents/httpcore-nio "4.4.6"]
[org.apache.httpcomponents/httpclient "4.5.3" :exclusions [[org.clojure/clojure]]]
[org.apache.httpcomponents/httpcore "4.4.6" :exclusions [[org.clojure/clojure]]]
[org.apache.httpcomponents/httpmime "4.5.3" :exclusions [[org.clojure/clojure]]]
Running mvn dependency:tree|grep http for the other project returns the following (note that this project is also a child of the parent):
[INFO] +- org.apache.httpcomponents:httpclient:jar:4.1.1:compile
[INFO] | +- org.apache.httpcomponents:httpcore:jar:4.1:compile
Is there a way I can ignore conflicts originating outside of my Clojure code, in lein (or otherwise)?
it's necessary to slog through the conflicts and fix them. There are two approaches:
Exclusions:
Exclude each dependency that is reported in lein deps tree from each of the upstream dependencies where it's provided. This gives you complete control when you need to make sure a transitive dependency is not included. It can though ... "be a bit of a bother" ;-)
Managed Dependencies:
You can also add a managed-dependencies section to your project.clj where you specify the exact version of libraries that will be used, regardless of the resolution of other transitive dependencies. This is a somewhat more blunt instrurment, and one i tend to turn to.
A random example from a project:
:managed-dependencies [[http-kit "2.3.0"]
[org.clojure/clojure "1.9.0"]
[ring/ring-core "1.6.0"]
[ring/ring-jetty-adapter "1.6.0"]
... lots more ...]

Clojure & ZeroMQ

Can anyone tell me some working dependencies to get up and running with zeromq and clojure?
I've tried several but leiningen isn't able to fetch them:
(Could not find artifact org.zmq:zmq:jar:2.1.0 in central (http://repo1.maven.org/maven2))
[org.zmq/zmq "2.1.0"]
[org.zmq/jzmq "1.0.0"]
I have compiled jzmq (/usr/local/share/java/jzmq.jar) and added this to my project.clj:
:native-path "/usr/local/lib"
There's a 2.0-SNAPSHOT here:
Lein should already have the clojars repo loaded.
What I propose is a mixture of what's already been proposed, but for the sake of completeness and hopefully to give a final answer I give it a try.
Since the dependency is not in the online repos I would include the jar(s) in the project's directory structure itself, e.g. in the directory repository and keep it in the source control system as the other files of the project. It's an important part of the project and without the dependency it won't run.
In this directory I would save the jar with the help of Maven Install plugin.
mvn install:install-file \
-Dfile=/usr/local/share/java/jzmq.jar \
-DgroupId=org.zeromq \
-DartifactId=jzmq \
-Dversion=2.1.0 \
-Dpackaging=jar \
-DlocalRepositoryPath=repository
When the jar file gets copied to the local repository, you define it and the dependency in project.clj as follows:
(defproject clojure-interal-repo-test "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.4.0"]
[org.zeromq/jzmq "2.1.0"]]
:repositories [["zeromq-repository" {:url "file:repository"
:snapshots false
:checksum :ignore
:update :never}]])
Within the project, run lein2 deps :tree to verify its correctness.
$ lein2 deps :tree
Retrieving org/zeromq/jzmq/2.1.0/jzmq-2.1.0.jar (4k) from file:repository/
[org.clojure/clojure "1.4.0"]
[org.zeromq/jzmq "2.1.0"]
Please note that the 4k above is the size of a fake file I created to test it out.
Read the document Repeatability in Leiningen's wiki should you need a bit more.
The only way I could get it to work was to use jeromq.
[org.zeromq/jeromq "0.3.2"]
Jeromq is native Java.
You can create a Maven local repository, install the compiled library into your local repo, and then, add the following to your project.clj
:repositories {"local" ~(str (.toURI (java.io.File. "your_local_repository_path")))}
Similar question, I have answered earlier here
Unfortunately, ZeroMQ is not present in public repository, at least at the last time I checked (a month ago I think). So you have to install the jar manually:
mvn install:install-file -Dfile=/usr/local/share/java/jzmq.jar -DgroupId=org.zeromq \
-DartifactId=jzmq -Dversion=2.1.0 -Dpackaging=jar
Then you can use the artifact as [org.zeromq/jzmq "2.1.0"] in your project.clj.

Is there an advantage to layering leiningen projects?

This is not a problem question, but a use of tools -- leiningen -- question.
Is there an advantage to creating hierarchical lein projects under one main project, and, if so, what is that advantage?
If I create a project using lein new bene-cmp, which is a Clojure "main" program
(defproject bene-cmp "1.0.4-SNAPSHOT"
:description "This is the main benetrak/GIC comparison program."
:dependencies [[org.clojure/clojure "1.4.0"]
[org.clojure/tools.cli "0.1.0"]
[clojure-csv/clojure-csv "1.3.2"]
[org.clojure/data.csv "0.1.2"]
[bene-csv "1.0.4-SNAPSHOT"]
[util "1.0.4-SNAPSHOT"]]
:omit-source true
:main bene-cmp.core)
and I want to write some Clojure scripts that will sanitize input files that will eventually be fed into bene-cmp by a bash script, should these be projects at the same level as bene-cmp, or under the bene-cmp project, and why?
Thanks.
I always look at the release cycle of the projects to determine if they are subprojects or "same level" projects. If you are always going to release the bene-sanitizers at the same time that bene-cmp, then they are subprojects or even just namespaces in the bene-cmp.

clojure lein: How do I include source from another directory in my project?

I have a lein project in one directory, and instead of using the .jar that gets downloaded when I run
> lein deps
I want to use the source from a cloned github repository (It has recent fixes not in the current jar). What is the canonical way to do this with leiningen?
Here is my project file:
(defproject oroboros "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.2.1"]
[org.clojure/clojure-contrib "1.2.0"]
[clojure-source "1.2.1"]
[overtone "0.3.0"]
[penumbra "0.6.0-SNAPSHOT"]]
:native-dependencies [[penumbra/lwjgl "2.4.2"]]
:dev-dependencies [[native-deps "1.0.5"]
[swank-clojure "1.4.0-SNAPSHOT"]])
I want to use the overtone repo from github, rather than the one from clojars.
https://github.com/overtone/overtone
Is this possible?
You can use checkout dependencies. From Leiningen's README:
Q: I want to hack two projects in parallel, but it's annoying to
switch between them.
A: Use a feature called checkout dependencies. If you create a
directory called checkouts in your project root and symlink some other
project roots into it, Leiningen will allow you to hack on them in
parallel. That means changes in the dependency will be visible in the
main project without having to go through the whole
install/switch-projects/deps/restart-repl cycle. Note that this is not
a replacement for listing the project in :dependencies; it simply
supplements that for tighter change cycles.
Back when I was using lein I simply put symlinks in my project directory to the checked out Overtone source dir.
I use cake for my Overtone hacking these days which has support for adding external projects to the class path. You just need to add the path to project.classpath in your project's .cake/config file:
project.classpath = /Users/sam/Development/improcess/lib/overtone/src:

Leiningen doesn't resolve my dependencies

I want to translate a Maven dependency to Leiningen:
<dependency>
<groupId>com.google.api.client</groupId>
<artifactId>google-api-client-parent</artifactId>
<version>1.4.1-beta</version>
</dependency>
I tried:
(defproject gdata2 "1.0.0-SNAPSHOT"
:description "FIXME: write"
:dependencies [[org.clojure/clojure "1.2.0"]
[org.clojure/clojure-contrib "1.2.0"]
[com.google.api.client/google-api-client-parent "1.4.1-beta"]])
However this doesn't work since there is no jar in the Maven central repository, just a parent pom. Leiningen tries to find google-api-client-parent-1.4.1-beta.jar and fails.
How do I tell Leiningen to just look at the pom and resolve the transitive dependencies?
Edit May 12
It seems that the code I need is not in the standard Maven repositories. I have to add the Leiningen equivalent of:
<repository>
<id>google-api-services</id>
<url>http://mavenrepo.google-api-java-client.googlecode.com/hg</url>
</repository>
And add google-api-services-tasks-1.0.0-beta.jar to the dependencies and then it is probably going to work. Will check and close this question when back from work :)
That POM project doesn't define any dependency, just a dependencyManagement section. You probably want to depend on real libraries (e.g. JARs), which will in turn pull the whole dependency tree into the picture while solving your problem.