I want to start nREPL from code and let Lighttable connect to it. Here is my attempt:
(ns test
(:require [clojure.tools.nrepl.server :refer [start-server default-handler]]
[lighttable.nrepl.handler :refer [lighttable-ops]])
(:gen-class))
(defn -main
[& args]
(start-server :port 8888
:handler (default-handler lighttable-ops)))
However when I connect from Lighttable I get this:
Jun 19, 2014 5:30:23 PM clojure.tools.nrepl.server invoke0
SEVERE: Unhandled REPL handler exception processing message {:data {:settings {:name "localhost:8888", :remote true, :client-id 67}}, :id 67, :op client.init, :session c4f51394-135e-4579-b367-a69bdcdef15e}
java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.Atom
at clojure.core$swap_BANG_.doInvoke(core.clj:2235)
at clojure.lang.RestFn.invoke(RestFn.java:529)
at lighttable.nrepl.handler$lighttable_ops$fn__6452.invoke(handler.clj:45)
at clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__491.invoke(middleware.clj:17)
at clojure.tools.nrepl.server$handle_STAR_.invoke(server.clj:18)
at clojure.tools.nrepl.server$handle$fn__803.invoke(server.clj:27)
at clojure.core$binding_conveyor_fn$fn__4145.invoke(core.clj:1910)
at clojure.lang.AFn.call(AFn.java:18)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
dependencies I have:
[org.clojure/clojure "1.6.0"]
[org.clojure/tools.nrepl "0.2.3"]
[lein-light-nrepl "0.0.18"]
It works if I run lein repl, but I really need to distribute the code as a jar package.
Try using #'lighttable-ops instead of just lighttable-ops.
I was able to reproduce the problem as you described, and this seemed to fix it.
I'm not sure why the error only occurs in the compiled jar, but I suspect it is something to do with the aot compilation that goes on in the jar-making process.
Related
I am following along with this example on creating a simple web service in Clojure using ring and jetty.
I have this in my project.clj:
(defproject ws-example "0.0.1"
:description "REST datastore interface."
:dependencies
[[org.clojure/clojure "1.5.1"]
[ring/ring-jetty-adapter "0.2.5"]
[ring-json-params "0.1.0"]
[compojure "0.4.0"]
[clj-json "0.5.3"]]
:dev-dependencies
[[lein-run "1.0.0-SNAPSHOT"]])
This in script/run.clj
(use 'ring.adapter.jetty)
(require '[ws-example.web :as web])
(run-jetty #'web/app {:port 8080})
And this in src/ws_example/web.clj
(ns ws-example.web
(:use compojure.core)
(:use ring.middleware.json-params)
(:require [clj-json.core :as json]))
(defn json-response [data & [status]]
{:status (or status 200)
:headers {"Content-Type" "application/json"}
:body (json/generate-string data)})
(defroutes handler
(GET "/" []
(json-response {"hello" "world"}))
(PUT "/" [name]
(json-response {"hello" name})))
(def app
(-> handler
wrap-json-params))
However, when I execute:
lein run script/run.clj
I get this error:
No :main namespace specified in project.clj.
Why am I getting this and how do I fix it?
You're getting this error because the purpose of lein run (according to lein help run) is to "Run the project's -main function." You don't have a -main function in your ws-example.web namespace, nor do you have a :main specified in your project.clj file, which is what lein run is complaining about.
To fix this, you have a few options. You could move the run-jetty code to a new -main function of the ws-example.web function and then say lein run -m ws-example.web. Or you could do that and also add a line :main ws-example.web to project.clj and then just say lein run. Or you could try using the lein exec plugin to execute a file, rather than a namespace.
For more info, check out the Leiningen Tutorial.
You have to put that (run-jetty) stuff into a -main somewhere and then add it to the project.clj like
:main ws-example.core)
From lein help run:
USAGE: lein run -m NAMESPACE[/MAIN_FUNCTION] [ARGS...]
Calls the main function in the specified namespace.
So, you would need to put your script.clj somewhere on the project source path and then call it as:
lein run -m script
Following http://www.webnoir.org/ instructions to create a new project - I ran lein uberwar - this generates a single (executable) jar - however it is not able to find the main class as mentioned in the manifest - no class file found.
The app runs run with "lein run".
Is the uberjar meant to be able to run this way (I expect it launches an embedded jetty?)
FYI Jar produced with lein uberjar fails on NoClassDefFoundError is similar - but out of date (this is with a newer version of leiningen where that specific bug is fixed).
The trick is to add gen-class to server.clj
(ns myproject.server ... (:gen-class))
For example:
I've just deployed using lein uberjar, and I have the following:
In my project.clj:
:main myproject.server
In my server.clj:
(ns myproject.server
(:require [noir.server :as server]
[myproject.views.common]
[myproject.views.index])
(:gen-class))
(server/load-views "src/myproject/views/")
(defn -main [& m]
(let [mode (keyword (or (first m) :dev))
port (Integer. (get (System/getenv) "PORT" "8080"))]
(server/start port {:mode mode
:ns 'myproject})))
require the views at the top
gen-class
load-views
Now it works fine to java -jar myproject-standalone.jar.
Building ring server-headless works -- lein ring server-headless -- but when I try to build the war or uberwar I get the following error, and cannot figure out why this is happening.
No namespaces to :aot compile listed in project.clj.
Exception in thread "main" java.lang.ExceptionInInitializerError, compiling:(ring/util/servlet.clj:62)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6416)
at clojure.lang.Compiler.analyze(Compiler.java:6216)
...
Caused by: java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at clojure.lang.RT.classForName(RT.java:2013)
at clojure.lang.Compiler$HostExpr.maybeClass(Compiler.java:938)
at clojure.lang.Compiler$HostExpr.access$400(Compiler.java:710)
at clojure.lang.Compiler.macroexpand1(Compiler.java:6342)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6395)
... 69 more
Caused by: java.lang.Exception: Cyclic load dependency: [ /servlet ]->/ring/util/servlet->[ /servlet ]
at clojure.core$check_cyclic_dependency.invoke(core.clj:5288)
at clojure.core$load.doInvoke(core.clj:5383)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.lang.Var.invoke(Var.java:401)
at servlet.<clinit>(Unknown Source)
... 76 more
My project.clj file is:
(defproject myproj "0.1"
:description "the sample"
:dependencies [
[org.clojure/clojure "1.3.0"]
[compojure "1.0.4"]
[hiccup "1.0.0"]
[clj-json "0.5.0"]
[ring/ring "1.1.0"]
[clj-http "0.1.1"]
]
:plugins [
[lein-ring "0.7.0"]
]
:ring {:handler routes/start})
If I remove the :ring {:handler routes/start} then I get a NPE somewhere else.
I don't know if I'm missing something in my project.clj, or if the particular version of lein is broken for this use case. Can someone clarify this for me?
I had the same issue, in my case the solution was as simple as doing a
lein clean
before the
lein ring uberwar
I think actual issue is that at some point, my handler was pointing to an incorrect/inexistent handler and that left a servlet.clj in the target/classes directory. Doing a clean will remove this file.
I solved the issue, which was a bit of a mistake on my part. Posting the answer here in case anyone makes the same mistake.
I had something like the following in src/routes.clj:
(defroutes main-routes
(GET "/some/path" [& params] (some-code params))
(route/resources "/")
(route/not-found "not found"))
(def start (run-jetty (handler/site main-routes) {:port 8080}))
This is all standard code to setup routes and provide a hook to start the jetty webapp from the command line via lein ring server-headless. Except that I declared start as a global instead of a function. That means when I run lein ring server-headless things still work, but when I run lein ring uberwar I end up with a weird configuration--a full jetty server will try to start up with it's servlet, AND uberwar has generated a servlet and is trying to package it into a jar.
When I was comparing my code against the compojure examples I kept missing this difference I guess because def and defn optically look so similar. But anyway I just made this change to get it working:
(defn start [] (run-jetty (handler/site main-routes) {:port 8080}))
The error says it all, the :aot param is missing from the project config. Check out this link for using :aot.
I have a simple web app with this project.clj:
(defproject squirrel-money "1.0.0-SNAPSHOT"
:description "Squirrel Money"
:dependencies [[org.clojure/clojure "1.2.0"]
[org.clojure/clojure-contrib "1.2.0"]
[compojure "0.5.3"]
[ring/ring-jetty-adapter "0.3.5"]
[hiccup "0.3.1"]
[postgresql "8.4-701.jdbc4"]
[clj-time "0.2.0-SNAPSHOT"]]
:dev-dependencies [[lein-eclipse "1.0.0"]]
:main squirrel-money.main
:repl-init-script "src/squirrel_money/init_repl.clj")
My main looks like this:
(ns squirrel-money.main
(:gen-class)
(:use
[compojure.core]
[ring.adapter.jetty])
(:require
[compojure.route :as route]
[squirrel-money.savings :as savings]))
(defn launch [routedef]
(run-jetty routedef {:port 17080}))
(defroutes money-routes
(GET "/savings" [] (savings/render))
(route/not-found "Page not found"))
(defn -main [& args] (launch money-routes))
With REPL works just fine. However, when I generate a jar with lein uberjar and try to execute it as:
java -jar squirrel-money-1.0.0-SNAPSHOT-standalone.jar
It dies with this exception:
Exception in thread "main" java.lang.NoClassDefFoundError: compojure/response/Renderable
at squirrel_money.main$fn__1067.invoke(main.clj:18)
at squirrel_money.main__init.load(Unknown Source)
at squirrel_money.main__init.<clinit>(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at clojure.lang.RT.loadClassForName(RT.java:1578)
at clojure.lang.RT.load(RT.java:399)
at clojure.lang.RT.load(RT.java:381)
at clojure.core$load$fn__4511.invoke(core.clj:4905)
at clojure.core$load.doInvoke(core.clj:4904)
at clojure.lang.RestFn.invoke(RestFn.java:409)
at clojure.lang.Var.invoke(Var.java:365)
at squirrel_money.main.<clinit>(Unknown Source)
Caused by: java.lang.ClassNotFoundException: compojure.response.Renderable
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
... 13 more
What am I doing wrong? How to get it to work?
Not sure if that matters, but I noticed that inside the jar my files, clojure itself and Java libs are unpacked as .class files, while all clojure libs are present only as plain .clj files.
This seems to be a leinigen 1.4.0 bug. You might want to try creating an uberjar with leiningen 1.3.1.
Edit:
Leiningen 1.4.0 deletes non-project .class files to work around a Clojure bug (see CLJ-322). Apparently this behavior can sometimes cause problems.
You can keep leiningen 1.4.0 from deleting non-project .class files by setting :keep-non-project-classes to true in your project.clj.
See the related leinigen issue for more info.
Hey, I'm new to Clojure and Leiningen and a bit stuck. I've managed to setup a project with Leiningen. I'm able to compile it into an uberjar and run the repl. I've also managed to load a dependency named aleph to run a simple concurrent webserver.
The next step for me is to use redis-clojure to access redis. But here I'm stuck. This is my project.clj:
(defproject alpha "0.0.1-SNAPSHOT"
:description "Just an alpha test script"
:main alpha.core
:dependencies [[org.clojure/clojure "1.2.0"]
[org.clojure/clojure-contrib "1.2.0"]
[aleph, "0.1.2-SNAPSHOT"]
[redis-clojure "1.2.4"]])
And here is my core.clj: Note that I only added the line (:requre redis) according to the example from redis-clojure.
(ns alpha.core
(:require redis)
(:gen-class))
(use `aleph.core 'aleph.http)
(defn alpha [channel request]
(let [] (enqueue-and-close channel
{:status 200
:header {"Content-Type" "text/html"}
:body "Hello Clojure World!"}))
(println (str request)))
(defn -main [& args]
(start-http-server alpha {:port 9292}))
When I try to run lein repl this happens:
java.io.FileNotFoundException: Could not locate redis__init.class or redis.clj on classpath: (core.clj:1)
Yes, I have run lein deps and the redis-clojure jar is available in my lib directory. I'm probably missing something trivial, but I've been at this issue for a few hours now and not getting any closer to a solution. Thanks!
Namespace redis does not exist. I suppose you need
(:require [redis.core :as redis])
A way to check for available namespaces:
(use 'clojure.contrib.find-namespaces)
(filter #(.startsWith (str %) "redis") (find-namespaces-on-classpath))
This works with more current versions of Clojure, in this example it finds the names of all namespaces that contains the sub string "jdbc":
(map str
(filter
#(> (.indexOf (str %) "jdbc") -1)
(all-ns)))
The result is a sequence, in example:
=>
("clojure.java.jdbc")