How to fix leiningen :aot warning - clojure

I am getting
Warning: specified :main without including it in :aot.
If you only need AOT for your uberjar, consider adding :aot :all into your
:uberjar profile instead.
Here is my project.clj
(defproject korma-test "0.1.0-SNAPSHOT"
:description "korma db test"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.5.1"]
[korma "0.3.0-RC5"]
]
:main korma-test.core)
and here is core.clj
(ns korma-test.core
(require [korma.db :as kdb])
(require [clojure.string :as str])
(:use [clojure.tools.cli])
(:import java.util.Date)
(:gen-class)
)
; Parses for options passed in on the command line.
(defn parse-opts
"Using the newer cli library, parses command line args."
[args]
(cli args
(optional ["-host" "Informix host" :default "localhost"] )
(optional ["-port" "Informix host's service port" :default "1498"] )
(required ["-username" "user name"] )
(required ["-password" "password"] )
(optional ["-database" "Informix host's database" :default "stores7/ministores.dbs" ] )))
(defn -main
[& args]
(if (= 0 (count args))
(println "Usage: korma-test --host <host-name> --port <port-num> --database <db-name>")
(let [opts (parse-opts args)
start-time (str (Date.))]
(def db-config {:classname "com.informix.jdbc.IfxDriver"
:subprotocol "postgresql"
:subname (format "//%s:(:port opts)/%s"
(:host opts)
(:database opts))
:user (:user opts)
:password (:password opts)})
(kdb/defdb db db-config)
(println opts))))
I'm confused as to where to put :aot to satisfy the warning.

I could have sworn it worked without warning before but in any case you now need to add an :aot directive in your project.clj
See here
The following works
project.clj
(defproject korma-test "0.1.0-SNAPSHOT"
:description "korma db test"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.5.1"]
[korma "0.3.0-RC5"]
[org.clojure/tools.cli "0.3.1"]]
:main korma-test.core
:aot [korma-test.core])
core.clj
(ns korma-test.core
(:require [korma.db :as kdb])
(:require [clojure.string :as str])
(:require [clojure.tools.cli :as c])
(:import java.util.Date)
(:gen-class))
; Parses for options passed in on the command line.
(defn parse-opts
"Using the newer cli library, parses command line args."
[args]
(c/cli args
[ ["-host" "Informix host" :default "localhost"]
["-port" "Informix host's service port" :default "1498"]
["-username" "user name"]
["-password" "password"]
["-database" "Informix host's database" :default "stores7/ministores.dbs" ]]))
(defn -main
[& args]
(if (= 0 (count args))
(println "Usage: korma-test --host <host-name> --port <port-num> --database <db-name>")
(let [opts (parse-opts args)
start-time (str (Date.))
db-config {:classname "com.informix.jdbc.IfxDriver"
:subprotocol "postgresql"
:subname (format "//%s:(:port opts)/%s"
(:host opts)
(:database opts))
:user (:user opts)
:password (:password opts)}]
(kdb/defdb db db-config)
(println opts))))

Related

clojure-api: Single main clj for multiple API handlers

The below is my app project.clj
(defproject clojure-my-app-api "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"}
:ring {:handler clojure-my-app-api.core/app}
:dependencies [[org.clojure/clojure "1.8.0"]
[metosin/compojure-api "1.1.10"]
[ring/ring-core "1.4.0"]
[ring/ring-jetty-adapter "1.4.0"]]
:main clojure-my-app-api.core)
and my app core.clj is
(ns clojure-my-app-api.core
(:require [ring.adapter.jetty :as jetty])
(:require [compojure.api.sweet :refer :all])
(:require [ring.util.http-response :refer :all]))
(defapi app
(GET "/hello" []
:query-params [name :- String]
(ok {:message (str "Dear " name ", Hello I am here ")})))
(jetty/run-jetty app {:port 3000})
My doubt is, Is it mandatory to put (jetty/run-jetty app {:port 3000}) in every clj class if we have multiple classes for handling multiple API requests.
Can you please help me out is there any single main class mechanism for multiple clj class to handle different API path.
I have modified my code.
project.clj
(defproject clojure-dauble-business-api "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"}
:ring {:handler {clojure-dauble-business-api.core/app
clojure-dauble-business-api.test/test1}}
:repl-options {:init-ns clojure-dauble-business-api.user}
:dependencies [[org.clojure/clojure "1.8.0"]
[metosin/compojure-api "1.1.10"]
[ring/ring-core "1.4.0"]
[ring/ring-jetty-adapter "1.4.0"]]
:main clojure-dauble-business-api.user)
user.clj
(ns clojure-dauble-business-api.user
(:require [ring.adapter.jetty :as jetty])
(:require [compojure.api.sweet :refer :all])
(:require [ring.util.http-response :refer :all])
(:require [clojure-dauble-business-api.core :as core])
(:require [clojure-dauble-business-api.test :as test]))
(jetty/run-jetty (list core/app test/test) {:port 3000})
core.clj
(ns clojure-dauble-business-api.core
(:require [ring.adapter.jetty :as jetty])
(:require [compojure.api.sweet :refer :all])
(:require [ring.util.http-response :refer :all]))
(defapi app
(GET "/hello" []
:query-params [name :- String]
(ok {:message (str "Dear " name ", Hello I am here ")})))
test.clj
(ns clojure-dauble-business-api.test
(:require [ring.adapter.jetty :as jetty])
(:require [compojure.api.sweet :refer :all])
(:require [ring.util.http-response :refer :all]))
(defapi test
(GET "/ping" []
:query-params [name :- String]
(ok {:message (str "Dear " name ", Hello I am here ")})))
Error while running http://localhost:3000/hello?name=acbd endpoint in Postman
2017-07-08 10:46:34.413:WARN:oejs.HttpChannel:qtp191004666-15: /hello?name=abcd
java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn
at ring.adapter.jetty$proxy_handler$fn__1401.invoke(jetty.clj:24)
at ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$ff19274a.handle(Unknown Source)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:497)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Thread.java:745)
You shouldn't have (jetty/run-jetty (list core/app test/test) {:port 3000}) in any of your namespaces. (Having it in user.clj is fine for REPL work).
Typically, you have a single handler route that you pass to ring for handing your application.
For example, I generally have a routes namespace that I combine by routes from other namespaces.
So, from your example.
(ns clojure-dauble-business-api.routes
:require [compojure.core :refer :all]
(clojure-dauble-business-api [core :as core]
[test :as t]))
(def app
(routes core/app t/test))
This is what you could pass into Jetty, or refer to in your :ring entry in your project.clj.
:ring {:handler clojure-dauble-business-api.routes}
You're getting the error, because run-jetty must be passed a function, but you're passing it a list instead (because you're trying to consolidate your routes with (list core/app test/test)
I would also add the plugin lein-ring to your project and remove the :main entry. You will also have to correct your :ring entry in your project as above.
I am a newbie too, but hope this helps:
This is how I have implemented. There is one file named user.clj which has
(jetty/run-jetty app {:port 3000})
and other common function that you may specify in main and then in project.clj
:repl-options {:init-ns user}
you can also use injections to load namespaces but I have never used them.

How can I run a Luminus project which uses Overtone?

I'm writing a web app which uses Overtone. When I try running the app using lein run or when I try to start the repl while in the project's directory I get the same error: java.lang.ExceptionInInitializerError at clojure.main.<clinit>(main.java:20) Caused by: java.lang.Exception: Server needs to be connected before you can perform this action.
It seems to me that both of those actions make all the files in my project compile. Is there any way to compile the namespaces which use Overtone after I run the server? Or maybe this isn't the issue, and the problem is coming from something else?
Here is my project.clj file:
(defproject comusic "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:dependencies [[buddy "1.3.0"]
[compojure "1.5.2"]
[conman "0.6.3"]
[cprop "0.1.10"]
[funcool/struct "1.0.0"]
[luminus-immutant "0.2.3"]
[luminus-migrations "0.3.0"]
[luminus-nrepl "0.1.4"]
[markdown-clj "0.9.98"]
[metosin/muuntaja "0.1.0"]
[metosin/ring-http-response "0.8.2"]
[mount "0.1.11"]
[org.clojure/clojure "1.8.0"]
[org.clojure/tools.cli "0.3.5"]
[org.clojure/tools.logging "0.3.1"]
[org.postgresql/postgresql "42.0.0"]
[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"]
[org.webjars/webjars-locator-jboss-vfs "0.1.0"]
[ring-webjars "0.1.1"]
[ring/ring-core "1.6.0-RC1"]
[ring/ring-defaults "0.2.3"]
[selmer "1.10.7"]
[overtone "0.10.1"]]
: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 comusic.core
:migratus {:store :database :db ~(get (System/getenv) "DATABASE_URL")}
:plugins [[lein-cprop "1.0.1"]
[migratus-lein "0.4.4"]
[lein-immutant "2.1.0"]]
:profiles
{:uberjar {:omit-source true
:aot :all
:uberjar-name "comusic.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.5.1"]
[pjstadig/humane-test-output "0.8.1"]]
:plugins [[com.jakemccrary/lein-test-refresh "0.18.1"]]
: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 {}})
EDIT: After booting a SC server and trying to connect to it in my main function I still get the same error. File which contains main function:
(ns comusic.core
(:require [comusic.handler :as handler]
[luminus.repl-server :as repl]
[luminus.http-server :as http]
[luminus-migrations.core :as migrations]
[comusic.config :refer [env]]
[clojure.tools.cli :refer [parse-opts]]
[clojure.tools.logging :as log]
[mount.core :as mount]
[overtone.core :as overtone])
(:gen-class))
(def cli-options
[["-p" "--port PORT" "Port number"
:parse-fn #(Integer/parseInt %)]])
(mount/defstate ^{:on-reload :noop}
http-server
:start
(http/start
(-> env
(assoc :handler (handler/app))
(update :port #(or (-> env :options :port) %))))
:stop
(http/stop http-server))
(mount/defstate ^{:on-reload :noop}
repl-server
:start
(when-let [nrepl-port (env :nrepl-port)]
(repl/start {:port nrepl-port}))
:stop
(when repl-server
(repl/stop repl-server)))
(defn stop-app []
(doseq [component (:stopped (mount/stop))]
(log/info component "stopped"))
(shutdown-agents))
(defn start-app [args]
(doseq [component (-> args
(parse-opts cli-options)
mount/start-with-args
:started)]
(log/info component "started"))
(.addShutdownHook (Runtime/getRuntime) (Thread. stop-app)))
(defn -main [& args]
(cond
(some #{"migrate" "rollback"} args)
(do
(mount/start #'comusic.config/env)
(migrations/migrate args (select-keys env [:database-url]))
(System/exit 0))
:else
(do
(overtone/connect-external-server 57110)
(start-app args))))

reloading from clojure file

I'm new to clojure and I'm trying to wrap my head around live reload in in clojure I want to be able to monitor/ watch all/ any project file and update the browser automatically
So far I have the following
(defproject app2 "0.1.0-SNAPSHOT"
:description "FIXME: write this!"
:url "http://exampl.com/FIXME"
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.9.89"]
[ring "1.5.0"]
[stasis "2.2.0"]
[hiccup "1.0.5"]
[clj-tagsoup "0.3.0"]
[optimus "0.18.5"]
[ring/ring-jetty-adapter "1.5.0"]
[cljs-ajax "0.5.8"]
[enfocus "2.1.1"]]
:plugins [[lein-cljsbuild "1.1.3"]
[lein-ring "0.9.7"]]
:cljsbuild {:builds [
{:id "dev"
:incremental true
:source-paths ["src/cljs"]
:compiler {
:main "scripts.client"
:output-to "resources/public/js/main.js"
:output-dir "resources/public/js/out"
:asset-path "js/out"
}}]}
:aliases {
"start-dev" ["pdo" ["cljsbuild" "auto"] ["ring" "server-headless"]]
}
:source-paths ["src"]
:resource-paths ["resources"]
:main app2.server
:repl-options {
:prompt (fn [ns] (str "your command for <" ns ">, master? " ))
:welcome (println "Welcome to the magical world of the repl!")
:init-ns app2.hawk
:init (app2.hawk/init)
:caught clj-stacktrace.repl/pst+
:skip-default-init false
:host "0.0.0.0"
:port 9000
:timeout 40000
}
:ring {
:init app2.hawk/init
:handler app2.server/app
:auto-reload? true :auto-refresh? true :reload-paths ["resources/public"]
:refresh-paths ["resrouces/public"]
}
:profiles {
:dev {
:repl-options {
:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]
}
:source-paths ["src"]
:ring {
:nrepl {
:start? true
:port 9000
:host "0.0.0.0"
}
}
:dependencies [
[ring-refresh "0.1.1"]
[http-kit "2.0.0"]
[org.clojure/tools.nrepl "0.2.11"]
[com.cemerick/piggieback "0.2.1"]
[hawk "0.2.10"]
]
:plugins [
[lein-pdo "0.1.1"]
]
}
}
)
for my handler I have
(ns app2.server
(:use [ring.middleware.resource :only [wrap-resource]]
[ring.middleware.file-info :only [wrap-file-info]]
[ring.middleware.file :only [wrap-file]]
[ring.middleware.reload :refer [wrap-reload]]
[ring.middleware.content-type :refer [wrap-content-type]]
[ring.middleware.refresh :refer [wrap-refresh]]
[ring.util.response :refer [file-response]]
)
(defn wrap-utf-8
"This function works around the fact that Ring simply chooses the default JVM
encoding for the response encoding. This is not desirable, we always want to
send UTF-8."
[handler]
(fn [request]
(when-let [response (handler request)]
(if (.contains (get-in response [:headers "Content-Type"]) ";")
response
(if (string? (:body response))
(update-in response [:headers "Content-Type"] #(str % "; charset=utf-8"))
response)))))
(defn handler [request]
(file-response (:uri request) {:root "resources/public"}))
(def app (-> handler
wrap-content-type
wrap-reload
wrap-refresh []
wrap-utf-8))
And then I am running hawk from repl
(ns app2.hawk
(:require [hawk.core :as hawk])
(:require [app2.server :refer [export-pages]]))
(defn init
[]
(export-pages)
(hawk/watch! [{:paths ["src/app2/templates" "resources/templates"]
:filter hawk/modified?
:handler (fn [ctx e]
(export-pages) ;; i'm compiling html pages dynamically to the server root but how do I then notify browser than html has changed? can i force server to reload from here?
ctx)}]))
If you don't mind using Boot instead of Leiningen, the system project will give you all the reload goodness you can expect from a Lisp, with plenty of examples.
Be sure to check the Holy Grail demo, which leverages system, to get started with minimal fuss.
It sounds like you have put together a great setup so far.
and for managing this workflow Figwheel is the logical next step. If you are doing any Clojurescript + clojure-web stuff you almost certainly should start with figwheel, you will have a much more pleasant experience.

lein run exits without running all of my -main function

Here's my project.clj:
(defproject fixurls "0.1.0-SNAPSHOT"
:description "Fixurls"
:url "https://github.com/swizzard/fixurls"
:license {:name "WTFPL"
:url "http://www.wtfpl.net/"}
:dependencies [[org.clojure/clojure "1.5.1"]
[clj-http "0.9.2"]
[org.clojure/data.json "0.2.4"]
[me.raynes/fs "1.4.4"]
]
:plugins [[lein-gorilla "0.2.0"]]
:jvm-opts ["-Xmx4g" "-Xms2g" "-Xss1g" "-server"]
:main ^:skip-aot fixurls.core
)
Here's ~/clojure-stuff/fixurls/src/core.clj:
(ns fixurls.core
(:require
[clj-http.client :as client]
[clojure.string :as string]
[clojure.java.io :as io]
[me.raynes.fs :as fs]
[clojure.data.json :as json]
)
(:import [java.net URL])
(:gen-class)
)
...
(defn process-file [in-file] (spit (get-fixed-name in-file)
(update-file in-file)))
(defn process-files [] (map process-file valid-files))
(defn -main [] (do (println "Hello, world!") (process-files)))
When I run lein run, all that happens, after a pause, is the printing of Hello, world! to stdout, and then lein exits. I've independently verified that the (process-files) part of -main isn't getting called. I can run (-main) from the repl and it works properly. What am I doing wrong?
The map function is lazy, and is not guaranteed process any input unless the corresponding output is accessed. If you are using map for side effects alone, wrap it in dorun. If you also need the result, use doall to force processing of the entire input.

Lein ring uberjar

I've built a very simple web app in Clojure (in fact I followed a tutorial). The project.clj file looks like this:
(defproject webdev "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.5.1"]
[ring "1.2.2"]
[hiccup "1.0.5"]
[compojure "1.1.6"]
[org.clojure/java.jdbc "0.3.3"]
[postgresql/postgresql "9.1-901.jdbc4"]]
:plugins [[lein-ring "0.8.10"]]
:ring {:handler (webdev.core/-main)
:port 8000}
:uberjar-name "webdev.jar"
:main webdev.core
:aot [webdev.core]
:profiles {:dev
{:main webdev.core/-dev-main}})
The relevant parts of my main webdev/core.clj look like this:
(defroutes routes
(GET "/about" [] about)
(ANY "/request" [] handle-dump)
(GET "/items" [] handle-index-items)
(POST "/items" [] handle-create-item)
(DELETE "/items/:item-id" [] handle-delete-item)
(PUT "/items/:item-id" [] handle-update-item)
(not-found "Page not found."))
(defn wrap-db [hndlr]
(fn [req]
(hndlr (assoc req :webdev/db db))))
(defn wrap-server-header [hndlr]
(fn [req]
(hndlr (assoc req :webdev/db db))))
(defn wrap-server-response [hndlr]
(fn [req]
(let [response (hndlr req)]
(assoc-in response [:headers "Server:"] "my-server"))))
(def sim-methods {"PUT" :put
"DELETE" :delete})
(defn wrap-simulated-methods [hndlr]
(fn [req]
(if-let [method (and (= :post (:request-method req))
(sim-methods (get-in req [:params "_method"])))]
(hndlr (assoc req :request-method method))
(hndlr req))))
(def app
(wrap-file-info
(wrap-resource
(wrap-server-response
(wrap-db
(wrap-params
(wrap-simulated-methods routes)))) "static")))
(defn -main [& [port]]
(items/create-table db)
(jetty/run-jetty #'app
{:port (if port (Integer/parseInt port)
(Integer/parseInt (System/getenv "PORT")))}))
(defn -dev-main [port]
(items/create-table db)
(jetty/run-jetty (wrap-reload #'app) {:port (Integer. port)}))
....
If I run Lein ring server or Lein ring uberjar on my project I get the following error:
java.lang.ClassCastException: clojure.lang.PersistentList
cannot be cast to clojure.lang.Named
If I run Lein run 8000. It works correctly and I can browse to localhost:8000
My Leiningen version is:
Leiningen 2.3.4 on Java 1.6.0_26 Java HotSpot(TM) 64-Bit Server VM
Anyone know what's wrong?
Regards,
Simon
That's looking wrong.
:ring {:handler (webdev.core/-main)
:port 8000}
(webdev.core/-main) means running your main function and delegating the result of the main Function as the handler to the ring-plugin.
Try using something more like this when using lein ring ...
:ring {:handler webdev.core/app
:port 8000}