if I use lein run the project is no problem.
But when I use jave -jar blog.jar after lein uberjar It happen exceptions.
16-Jul-20 11:28:05 DESKTOP-C3SC9AR INFO [slf4j-timbre.adapter] - >> starting.. *db*
Exception in thread "main" java.lang.RuntimeException: could not start [*db*] due to
.....
Caused by: java.lang.Exception: :jdbc-url, :datasource, or :datasource-
AND my project.clj file
(defproject blog "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:dependencies ....
:min-lein-version "2.0.0"
:uberjar-name "blog.jar"
:jvm-opts ["-server"]
:main blog.core
:migratus {:store :database}
:plugins [[lein-environ "1.0.1"]
[migratus-lein "0.2.0"]]
:profiles
{:uberjar {:omit-source true
:env {:production true}
:aot :all
:source-paths ["env/prod/clj"]}
:dev [:project/dev :profiles/dev]
:test [:project/test :profiles/test]
:project/dev ...
:project/test ...
:profiles/dev {:env {:database-url "jdbc:postgresql://localhost/blog?user=postgres&password=root"}}
:profiles/test {}})
Maybe it can't find the key of "database-url"?
Data provided via environment settings in project.clj are not provided when you use java directly. It's your responsibility to make sure the environment settings visible to the app provide any credentials or connection info needed.
It could look something like:
DATABASE_URL="jdbc...." java -jar my-project-standalone.jar
Related
I am building a server program to provide an API to a mongo database containing details of photos. All works well running it from the REPL, or if I start it using lein run.
The problems happen when I try and run the uberjar. Building the uberjar works ok:
(master) photo-api: lein uberjar
Compiling photo-api.env
Compiling photo-api.config
Compiling photo-api.core
WARNING: find-keyword already refers to: #'clojure.core/find-keyword in namespace: image-lib.core, being replaced by: #'image-lib.core/find-keyword
Compiling photo-api.db.core
Compiling photo-api.handler
Compiling photo-api.layout
Compiling photo-api.middleware
Compiling photo-api.routes.home
Compiling photo-api.routes.services
Created /Users/iain/Code/Clojure/Luminus/photo-api/target/uberjar/photo-api-0.1.0-SNAPSHOT.jar
Created /Users/iain/Code/Clojure/Luminus/photo-api/target/uberjar/photo-api.jar
(master) photo-api:
but running the jar gives an error:
(master) photo-api: java -jar target/uberjar/photo-api.jar
WARNING: find-keyword already refers to: #'clojure.core/find-keyword in namespace: image-lib.core, being replaced by: #'image-lib.core/find-keyword
read config from resource: "config.edn"
Exception in thread "main" java.lang.RuntimeException: could not start [#'photo-api.db.core/db*] due to
at mount.core$up$fn__420.invoke(core.cljc:92)
at mount.core$up.invokeStatic(core.cljc:92)
at mount.core$up.invoke(core.cljc:90)
at mount.core$bring.invokeStatic(core.cljc:210)
at mount.core$bring.invoke(core.cljc:202)
at mount.core$start.invokeStatic(core.cljc:252)
at mount.core$start.doInvoke(core.cljc:244)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at mount.core$start_with_args.invokeStatic(core.cljc:350)
at mount.core$start_with_args.doInvoke(core.cljc:346)
at clojure.lang.RestFn.invoke(RestFn.java:410)
at photo_api.core$start_app.invokeStatic(core.clj:42)
at photo_api.core$start_app.invoke(core.clj:41)
at photo_api.core$_main.invokeStatic(core.clj:50)
at photo_api.core$_main.doInvoke(core.clj:49)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.AFn.applyToHelper(AFn.java:152)
at clojure.lang.RestFn.applyTo(RestFn.java:132)
at photo_api.core.main(Unknown Source)
Caused by: java.lang.NullPointerException
at com.mongodb.ConnectionString.<init>(ConnectionString.java:222)
at com.mongodb.MongoClientURI.<init>(MongoClientURI.java:189)
at com.mongodb.MongoClientURI.<init>(MongoClientURI.java:171)
at monger.core$connect_via_uri.invokeStatic(core.clj:230)
at monger.core$connect_via_uri.invoke(core.clj:230)
at photo_api.db.core$fn__12620.invokeStatic(core.clj:29)
at photo_api.db.core$fn__12620.invoke(core.clj:28)
at mount.core$record_BANG_.invokeStatic(core.cljc:86)
at mount.core$record_BANG_.invoke(core.cljc:85)
at mount.core$up$fn__420.invoke(core.cljc:93)
... 18 more
Or the SNAPSHOT jar.
(master) photo-api: java -jar target/uberjar/photo-api-0.1.0-SNAPSHOT.jar
Exception in thread "main" java.lang.NoClassDefFoundError: clojure/lang/Var
at photo_api.core.<clinit>(Unknown Source)
Caused by: java.lang.ClassNotFoundException: clojure.lang.Var
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
(master) photo-api:
What am I missing here? I'm guessing it's something to do with dev build and production build differences, but I can't spot anything obvious and the error messages are not a lot of help to me.
This is the project file which as far as I remember is mostly straight from the original luminus template:
(defproject photo-api "0.1.0-SNAPSHOT"
:description "API for geting data from photos db"
:url "http://soulflyer.com"
:dependencies [[cider/cider-nrepl "0.14.0"]
[clj-time "0.13.0"]
[com.google.guava/guava "20.0"]
[com.novemberain/monger "3.1.0" :exclusions [com.google.guava/guava]]
[compojure "1.6.0"]
[cprop "0.1.10"]
[funcool/struct "1.0.0"]
[luminus-immutant "0.2.3"]
[luminus-nrepl "0.1.4"]
[luminus/ring-ttl-session "0.3.2"]
[markdown-clj "0.9.99"]
[metosin/compojure-api "1.1.10"]
[metosin/muuntaja "0.3.1"]
[metosin/ring-http-response "0.9.0"]
[mount "0.1.11"]
[org.clojure/clojure "1.8.0"]
[org.clojure/tools.cli "0.3.5"]
[org.clojure/tools.logging "0.4.0"]
[org.clojure/data.json "0.2.6"]
[org.webjars.bower/tether "1.4.0"]
[org.webjars/bootstrap "4.0.0-alpha.5"]
[org.webjars/font-awesome "4.7.0"]
[org.webjars/jquery "3.1.1"]
[ring-webjars "0.2.0"]
[ring/ring-core "1.6.1"]
[ring/ring-defaults "0.3.0"]
[selmer "1.10.7"]
[image-lib "0.2.1-SNAPSHOT"]]
:min-lein-version "2.0.0"
:jvm-opts ["-server" "-Dconf=.lein-env"]
:source-paths ["src/clj"]
:test-paths ["test/clj"]
:resource-paths ["resources"]
:target-path "target/%s/"
:main ^:skip-aot photo-api.core
:plugins [[lein-cprop "1.0.3"]
[org.clojars.punkisdead/lein-cucumber "1.0.5"]
[lein-immutant "2.1.0"]]
:cucumber-feature-paths ["test/clj/features"]
:profiles
{:uberjar {:omit-source true
:aot :all
:uberjar-name "photo-api.jar"
:source-paths ["env/prod/clj"]
:resource-paths ["env/prod/resources"]}
:dev [:project/dev :profiles/dev]
:test [:project/dev :project/test :profiles/test]
:project/dev {:dependencies [[prone "1.1.4"]
[ring/ring-mock "0.3.0"]
[ring/ring-devel "1.6.1"]
[pjstadig/humane-test-output "0.8.2"]
[clj-webdriver/clj-webdriver "0.7.2"]
[org.apache.httpcomponents/httpcore "4.4"]
[org.clojure/core.cache "0.6.3"]
[org.seleniumhq.selenium/selenium-server "2.48.2"]]
:plugins [[com.jakemccrary/lein-test-refresh "0.19.0"]
[refactor-nrepl "2.3.0-SNAPSHOT"]]
:source-paths ["env/dev/clj"]
:resource-paths ["env/dev/resources"]
:repl-options {:init-ns user}
:injections [(require 'pjstadig.humane-test-output)
(pjstadig.humane-test-output/activate!)]}
:project/test {:resource-paths ["env/test/resources"]}
:profiles/dev {}
:profiles/test {}})
I think you're just missing required configuration - at least Mongo connection string.
When running in dev mode, the luminus (and cprops configuration library) uses the config from your profiles.clj.
However, this is the leiningen thing and it's not available when running from uberjar.
You can specify all your "production" configuration in "config.edn" file and run uberjar like this:
java -Dconf=config.edn -jar target/uberjar/photo-api.jar
You can also use java system properties to set configuration values one by one.
See http://www.luminusweb.net/docs/environment.md for more details.
In my project.cli I have a dependency on clj-http that is used for tests only, with clj-http.client.
When I look at the uberjar file created for that project, I see that the class fils associated with this dependency are included. That makes the jar file bigger than it need be.
So, is there a way to define a dependency in clojure such that it is only used during tests, and is not included in the uberjar?
I know that I could do this in a pom.xml, but the pom.xml is generated when using clojure, so I only have recourse to something that works in the project.clj file.
To add more colour, my project.clj looks like this
(defproject aproject "0.1.0-SNAPSHOT"
:description "A project"
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/data.json "0.2.6"]
[compojure "1.5.0"]
[hiccup "1.0.5"]
[http-kit "2.1.18"]
[org.clojure/tools.logging "0.3.1"]
[ch.qos.logback/logback-classic "1.1.7"]
[ring/ring-devel "1.4.0"]]
:plugins [[lein-ring "0.9.7"]]
:ring {:handler aproject.core/app-routes}
:main ^:skip-aot aproject.core
:target-path "target/%s"
:resources-paths ["resources/"]
:profiles {:uberjar {:aot :all}
:dev {:dependencies [[peridot "0.4.3"]
[midje "1.8.3"]]
:plugins [[lein-midje "3.2.1"]]
:aliases {"test" ["midje"]}}
:test {:dependencies [[clj-http "3.5.0"]
[midje "1.8.3"]]
:plugins [[lein-midje "3.2.1"]]}
})
I am running the tests like this:
lein with-profile test midje :filters dt
What I am seeing is:
Exception in thread "main" java.io.FileNotFoundException: Could not locate midje/util/ecosystem__init.class or midje/util/ecosystem.clj on classpath., compiling:(/private/var/folders/7l/0fwd_7ls1m19q3_z1_tgg1w80000gn/T/form-init7253661442775183594.clj:1:125)
at clojure.lang.Compiler.load(Compiler.java:7391)
The filter probably does not affect this, but just in case the test looks like this:
(ns aproject.deployment.core
(:require [midje.sweet :refer :all]
[clj-http.client :as client]
[peridot.core :as p]
[clojure.data.json :as json]
[front-end.core :as fe]))
(facts "'aproject' deployed" :dt
(let [response (client/get "http://localhost:8080/ping")]
(response :status) => 200
))
I can see that the test profile is being triggered, and I seem to have the dependency for midje, and the plugin, but ...?
Thanks
Nathan
Add it to the :test profile, then run your tests with lein with-profile test midje :filters dt. Generate your uberjar as usual, lein uberjar and it shouldn't include the extra files.
I am trying to update lein-resource to use clojure.spec which requires the alpha version of Clojure [org.clojure/clojure "1.9.0-alpha13"]. When I add the dependency it compiles ok but the REPL and testing use the lein version of Clojure 1.8.0.
If I set :eval-in-leiningen to false, it respects the Clojure dependency.
How can I test a lein plugin with a different version of Clojure without disabling the ability for it to run as a plugin?
I'm guessing that your project.clj is getting overridden by your file ~/.lein/profiles.clj. Mine looks like this:
> cat ~/.lein/profiles.clj
{ :user {
:plugins [
[com.jakemccrary/lein-test-refresh "0.16.0"]
[jonase/eastwood "0.2.3"]
[lein-ancient "0.6.0"]
[lein-codox "0.9.3"]
[lein-exec "0.3.6"]
]
:dependencies [
[org.clojure/clojure "1.9.0-alpha13"]
]
:test-refresh { :quiet true
:changes-only true }
; :jvm-opts ["-Xms1g" "-Xmx4g" ] ; "-server"
}
}
I'm assuming your project.clj should look something like this:
(defproject clj "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.9.0-alpha13"]
[tupelo "0.9.9"]
]
:java-source-paths ["/home/alan/xpr/src"]
:main ^:skip-aot clj.core
:target-path "target/%s"
:profiles {:dev {:dependencies [[org.clojure/test.check "0.9.0"]] }
:uberjar {:aot :all}}
)
Fix up your ~/.lein/profiles.clj and you should have no problem.
Turns out the problem is :eval-in-leiningen true in the project.clj. It is a bit of a catch-22. If it is there, it forces the test to run with the version of Clojure defined with the installed with lein. If it is removed, the lein dependecies in the code are not resolved.
Does cljc / lein / clojurescript work yet?
I was previously using cljx, and was able to compile the same project with the cljx plugin for lein firing off a cljsbuild task.
Now I'm switching to cljc, I want to compile my cljc files into both compiled Java and into javascript for use in the browser.
Here's my current project.clj file
(defproject com.mysite/myproj "0.3.2-SNAPSHOT"
:description ""
:url ""
:license {:name "Gnu Lesser Public License"
:url "https://www.gnu.org/licenses/lgpl.html"}
:dependencies [[org.clojure/clojure "1.7.0"]]
:plugins [[lein-cljsbuild "1.0.3"]
[lein-localrepo "0.4.0"] ]
:source-paths ["cljc" "src" ]
:cljsbuild {:builds [{
:source-paths ["cljc" ]
:compiler {
:output-to "browser-based/js/main.js"
:optimizations :whitespace
:pretty-print true }
} ]}
:hooks [leiningen.cljsbuild]
:aot [myproj.core]
:main myproj.core)
I don't remember exactly where I copied some of this from, but I assume that the leiningen.cljsbuild hook was what automatically fired off the cljs build process. However after removing the cljx plugin, and moving to cljc, this is successfully compiling the Java version of my program but doesn't seem to be producing any javascript.
Yes, it works.
Try with:
(defproject com.mysite/myproj "0.3.2-SNAPSHOT"
:description ""
:url ""
:license {:name "Gnu Lesser Public License"
:url "https://www.gnu.org/licenses/lgpl.html"}
:dependencies [[org.clojure/clojure "1.7.0"]
[org.clojure/clojurescript "1.7.28"]
:plugins [[lein-cljsbuild "1.0.6"]
[lein-localrepo "0.4.0"]]
:source-paths ["cljc" "src"]
:cljsbuild {:builds [{
:source-paths ["cljc" "src"]
:compiler {:output-to "browser-based/js/main.js"
:optimizations :whitespace
:pretty-print true}}]}
:hooks [leiningen.cljsbuild])
Then run: lein compile or lein cljsbuild once
Please note that I changed the :source-paths under :cljsbuild to include "src": :source-paths ["cljc" "src"]. Apart from that I added an explicit dependency on clojurescript and bumped cljsbuild version to 1.0.6
By the way, why do you have a separate cljc directory? You can have your cljc, clj & cljs files sharing the same directory structure.
I'm trying to run lein ragtime migrate on a heroku dyno. Normally, I would set the database path in my project.clj like so:
(defproject my-project "0.1.0-SNAPSHOT"
:min-lein-version "2.0.0"
:dependencies [[org.clojure/clojure "1.6.0"]
[org.clojure/java.jdbc "0.3.7"]
[postgresql "9.3-1102.jdbc41"]
[ragtime "0.3.9"]
[ring "1.4.0-RC1"]
[ring/ring-defaults "0.1.2"]]
:plugins [[lein-ring "0.8.13"]
[ragtime/ragtime.lein "0.3.9"]]
...
:ragtime {:migrations ragtime.sql.files/migrations
:database (System/getenv "DATABASE_URL")}
...
:profiles
{:dev {:dependencies [[javax.servlet/servlet-api "2.5"]
[ring-mock "0.1.5"]]
:test {:ragtime {:database (System/getenv "DATABASE_URL")}}})
When I run the command, I get the following error both locally and depolying over Heroku
java.lang.IllegalArgumentException: No method in multimethod 'connection' for dispatch value: postgres
Any pointers in the right direction would be very appreciated.
Ragtime 0.3.9 uses the scheme from the connection url as the dispatch value for the connection multimethod. The code is here and here. But the DATABASE_ENV from heroku doesn't have a "jdbc" but a "postgres" scheme (which makes sense, it has to be generic).
A workaround could be to add the "jdbc://" prefix:
:ragtime {:migrations ragtime.sql.files/migrations
:database ~(str "jdbc://" (System/getenv "DATABASE_URL"))}
You can also upgrade to [ragtime "0.4.0"] which doesn't use the scheme to find out how to create the connection. See the wiki for info about the upgrade path from 0.3.x