Issue with lein ring uberjar and profiles - clojure

I am having troubles to make lein ring uberjar work with multiple profiles.
The following works:
lein new luminus profile-issue
cd profile-issue
lein ring uberjar
java -jar target\profile-issue-0.1.0-SNAPSHOT-standalone.jar
Now, when working with multiple profiles the following change to project.clj is important.
;add key to project.clj
:target-path "target/%s/"
Next attempt
lein clean
lein ring uberjar
java -jar target\profile-issue-0.1.0-SNAPSHOT-standalone.jar
Error: Could not find or load main class profile_issue.handler.main
The reason why it's important to split the target path into subdirectories when working with multiple profiles is explained here, around line 250. In a nutshell, when using :target-path "target/ you'll end up in troubles because different profiles compile into the same directory and when you start the REPL without a lein clean, you don't really know what you get.
And btw, when using :target-path "target/%s/" the jar and uberjar don't end up in the same directory which is weird.
Any idea?

Related

Leiningen missing test resources?

Leiningen provides a default directory for 'main' code, main resources, and test code, but nothing for test resources.
Coming from a maven background this is something I'd expect.
In that case, where should test resources live? Or a larger question, what's the philosophical reason why it wouldn't need a test resources directory
Test resources in Leiningen are managed using profiles. To set up a directory with test resources, you would add its path to the :resource-paths property of the :test profile (to make it available only to the test task) or :dev profile (to make it available to all dev tasks, e.g. test, run, repl, etc.)
Sample project.clj for a Maven-like project structure:
(defproject myproject "0.0.1-SNAPSHOT"
:source-paths ["src/main/clj"]
:test-paths ["src/test/clj"]
:resource-paths ["src/main/resources"]
:dev {:resource-paths ["src/test/resources"]})
When the :dev profile is active, its :resource-paths values are merged with the :resource-paths from the base project, giving you what you're looking for.
See the Leiningen docs for more information on profiles.

Clojure - Ring uberjar specify port

How can I generate a standalone ring uberjar that listens to a given port ?
When developing I launch my app with the following leiningen/ring command, in which I can specify the port :
lein with-profile dev ring server-headless 9696
Now I want to deploy it, so I ran :
lein with-profile prod ring uberjar 9696
But I got an error :
Error encountered performing task 'ring' with profile(s): 'prod'
clojure.lang.ArityException: Wrong number of args (2) passed to: uberjar/uberjar
So I added a :portin my project.clj :
:ring {:handler img-cli.handler/handler
:init img-cli.handler/init
:destroy img-cli.handler/destroy
:port 9696}
lein with-profile prod ring uberjar
java -jar my-jar.jar
But then I see in the logs : Started server on port 3000
How do I generate an uberjar with the port that I want ?
Note : just in case, I'm using compojure.
It turns out that my use of the profile was problematic.
A closer looks at the profile documentation yields :
To activate a profile in addition to the defaults, prepend it with a
+:
$ lein with-profile +server run
Therefore I had to use lein with-profile +prod ring uberjar 9696 (notice the +).

How to configure Leiningen to use a corporate repository?

We are hosting a corporate repository which acts as a proxy to the well-known repositories (e.g. Maven Central and Clojars). I want Leiningen to hit the corporate repository in the first place. Only when the corporate repository fails to deliver the artifact Leiningen should ask the standard repositories. This should be the default behaviour of all my projects. What configuration I have to do?
I have added the corporate repository as a mirror in ~/.lein/profiles.clj:
{:user {:mirrors {"our-repo" {:name "our-repo"
:url "http://our-repo/all/"}}}}
Unfortunately this setting has no impact. Leiningen downloads the artifacts from Maven Central:
PS> lein repl
Retrieving org/clojure/clojure/1.5.1/clojure-1.5.1.pom from central
...
Update
xsc suggests to overwrite the Maven Central repository with a mirror definition which points to the corporate repository. It works. Now instead of going to the external Maven Repository Leiningen retrieves the artifacts from the corporate repository.
S/He also suggests to specify an additional repository definition to install a fallback mechanism.
Unfortunately this does not work so well because Leiningen complains about this setting:
:repositories detected in user-level profiles! [:user]
See https://github.com/technomancy/leiningen/wiki/Repeatability
This warning is very annoying. For this reason I would abstain from this setting. Is there another way to install a fallback mechanism?
Here's what works for me:
{:user {:mirrors {#".+" {:url "http://nexus.example.com:8081/nexus/content/groups/public"}}
:repositories [["snapshots" {:id "NudaySnapshots"
:url "http://nexus.example.com:8081/nexus/content/repositories/snapshots"}]
["releases" {:id "NudayReleases"
:url "http://nexus.example.com:8081/nexus/content/repositories/releases"
:sign-releases false}]]}
:auth {:repository-auth {#"nexus.example.com" {:username "deployment"
:password "foo bar baz"}}}}
This handles both resolving dependencies through my Nexus mirror and publishing artifacts to it with lein deploy.
I get the annoying "Repeatability" warning, but I'm working on getting rid of that.
As far as I can see in Leiningen's example project.clj you have to use the name of the repository to mirror as the key in the :mirrors map. So, try this:
{:mirrors {"central" { ... }}}
This will most likely replace the repository completely, so you might want to add the original again:
{:mirrors {"central" {:url "..." }}
:repositories {"maven" {:url "http://repo1.maven.org/maven2/"}}}

How do I use checked-in jars with leiningen

We have some 3rd-party jars checked-in to our project. We'd like to add them to the classpath. That's it. We don't want to set up a local maven repo (because that would break our 'check out and run' philosophy). Each developer would have to set up their own maven repo, distinct from the project.
Is there a way to do this or is this? Most of the answers I've seen say to set up a local maven which we don't want or need just to add a jar to a classpath.
You will need to setup a local maven repository, but that can be a simple directory, in your project directory, that you then check in to source control. (Which will maintain your 'check out and run' policy)
As of Leiningen 2.2.0 the functionality to deploy jars is built-in with the lein deploy task. So, the task has simplified from previous versions.
Create a directory inside your project called, in this example, myrepo. (The name is arbitrary)
Add a :repositories entry in your project.clj file with a path to the local directory you created.
:repositories [["localrepo1" "file:myrepo"]]
Deploy your free floating jar to the repo.
lein deploy localrepo1 com.blueant/fancypants 1.0.1 fancypants.jar
And, add your dependency to your project.clj :dependencies vector as normal.
:dependencies [[com.blueant/fancypants "1.0.1"]]
The deploy task will generate the checksums and directory structure required to to tie into the lein dependency resolution. You can verify your jar is loaded correctly with the lein deps :tree command.
Note: File paths in :repositories are formatted as URLs. So, /Users/user1/Desktop is file:///Users/user1/Desktop, and, a local directory within the project, myrepo is file:myrepo.
I'd like to elaborate on #Jared314's excellent answer that helped me as well.
Below is a script that automates the process of adding multiple jars from a local lib folder to a local repository:
#!/bin/sh
export LOCALREPO_USERNAME=
export LOCALREPO_PASSWORD=
for file in lib/*.jar
do
name=$(basename "$file")
basename=${name%.jar}
echo "Deploying $basename"
artifactId="local/$basename"
lein deploy localrepo1 $artifactId 1.0 $file
echo "[$artifactId \"1.0\"]" >> dependencies.log
done
The list of Leiningen dependencies that can be added to project.clj is stored in dependencies.log.
Before running the script, :repositories entry in project.clj has to be updated to allow for reading repository username and password from the environment:
:repositories [["localrepo1" {:url "file:myrepo"
:username :env/localrepo_username
:password :env/localrepo_password}]]
This will prevent the repository password prompt from displaying when running the script.
This question has already been answered here.
It is indeed possible, but there's a reason why maven and dependency management exists. If you have many dependencies changing versions creating a repo is the recommended approach.

How can I install Leiningen packages behind a firewall?

I use a local library to do some development, but the firewall prevents alot of internet sites. Is there a way to download artifacts manually?
My project.clj is:
https://github.com/zubairq/coils/blob/master/project.clj?
Update
From the comments given I am understanding that the steps to take are:
1) Install Maven
2) Find out which jars are in my project (How can I do this based on my project.clj?)
Dependency Tree
In order to figure out which jars your project needs you can do:
$ lein deps :tree
Which will show you something that is called a "dependency tree". It will look similar to:
[clj-time "0.5.0"]
[joda-time "2.2"]
[clojure-complete "0.2.3"]
[org.myproject/some-proto "0.0.1-20130523.145830-9"]
[org.flatland/protobuf "0.7.2"]
[ordered-collections "0.4.0"]
[org.flatland/schematic "0.1.0"]
[org.flatland/useful "0.9.0"]
[com.datomic/datomic-free "0.8.3862"]
...
Installing Jars with Lein
One simple way to install manually downloaded jars would be to use "lein-localrepo":
$ lein localrepo install [-r repo-path]
[-p pom-file]
<filename>
<[groupId/]artifactId>
<version>
Here are a couple of examples (given that you have downloaded the jars):
$ lein localrepo install foo-1.0.6.jar com.example/foo 1.0.6
$ lein localrepo install foomatic-1.3.9.jar foomatic 1.3.9
Take a look at the documentation for more features and examples.
Installing lein-localrepo
You can install lein-localrepo as a plugin by adding the following to your ~/.lein/profiles.clj:
{:user {:plugins [[lein-localrepo "0.5.2"]]}}
Lein Behind a Proxy Server
In case it is "ok" to use a proxy server, you can add it to ~/.lein/profiles.clj under jvm-opts
{:user {:jvm-opts ["-Dhttp.proxyHost=168.1.1.104" "-Dhttp.proxyPort=8080"]}}
where user is a profile name to use.
Or you can export http_proxy environment variable before launching lein.