I get a strange error when I load my Clojure project and I was wondering why it happens and why my workaround works:
I get a NullpointerException error when I start my clojure project with lein repl, which loads in one of my Clojure files (which contains a lot of functions). My workaround is that I comment out the main content of the the last 3 functions in the file and load the project. When there's no error message, I exit it, uncomment the parts (effectively restoring the initial file) and it finally loads and doesn't show any error messages.
It's kind of strange that it loads the second time but not the first time.
Does this happen to anyone else? I didn't include my code because it is 600+ lines of different functions.
Edit: Providing stack trace and full report. It seems to be only the -main function that causes the error. If I comment out the content (leaving only the header) and run lein repl, it compiles fine. Then I uncomment the content, and run lein repl, there is no NPE. Only after a while it happens again.
(defn -main [prev curr act cstm]
(if (or (nil? prev) (empty? prev))
curr
(let [other-prev-concepts (filter #(not(is-object %)) prev)
prev (filter #(is-object %) prev)
newpstm prev
newpstm (filter #(is-object %) newpstm)
newpstm (adjust-poses-from-camera-move (first act) newpstm)
other-curr-concepts (filter #(not(is-object %)) curr)
curr-cycle (filter #(is-object %) curr)
results (if (< (count curr-cycle) (count newpstm))
(map reverse (get (find-alignment curr-cycle newpstm) :assignments))
(get (find-alignment newpstm curr-cycle) :assignments))
aligned (filter #(< (apply get-distance %) maxWeight*) results)
mapped-pstm (map second aligned)
pstm-map (convert-to-map-of-map curr-cycle)
prev-map (convert-to-map-of-map newpstm)
newprev
(loop [remaining aligned
result {}]
(if (empty? remaining)
result
(let [[head & others] remaining
old (second (first head))
new (second (second head))
mapped-old (map second (map first aligned))
new-fields (get pstm-map new)
updated-prev (assoc result old new-fields)
conf (get-in prev-map [old :*conf])
new-conf (min (+ conf confInc*) 1)
updated-prev (assoc-in updated-prev [old :*conf] new-conf)
children (map second (filter #(and (= old (last %)) (= 'attached (first %))) cstm) )
children-to-update (remove (set mapped-old) children)
updated-prev (update-children (get prev-map old) (get pstm-map new)
children-to-update prev-map updated-prev cstm mapped-old)
]
(recur others updated-prev)
)
))
mapped-prev (map second (map first aligned))
newprev (convert-map-to-list newprev)
newprev (disapps act newpstm curr-cycle newprev cstm)
newprev (apps mapped-pstm curr-cycle newprev)
]
(concat newprev other-curr-concepts)
)
)
)
Stack trace:
$ lein repl
If there are a lot of uncached dependencies this might take a while ...
Compiling proj.core
Nov 19, 2020 3:08:58 PM clojure.tools.logging$eval175$fn__178 invoke
INFO: Executing python initialize with options:{:python-executable nil, :program-name nil, :python-home nil, :library-path nil}
Nov 19, 2020 3:08:58 PM clojure.tools.logging$eval175$fn__178 invoke
INFO: Detecting startup-info for Python executable:
Nov 19, 2020 3:08:58 PM clojure.tools.logging$eval175$fn__178 invoke
INFO: Startup info detected: {:python-home "/home/user/miniconda3/envs/usr", :lib-version "3.6", :libname "python3.6m", :java-library-path-addendum "/home/user/miniconda3/envs/usr/lib"}
Nov 19, 2020 3:08:58 PM clojure.tools.logging$eval175$fn__178 invoke
INFO: Setting java library path: /home/user/miniconda3/envs/usr/lib:/home/user/catkin_ws/devel/lib:/opt/ros/melodic/lib:/usr/java/packages/lib:/usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib
Nov 19, 2020 3:08:58 PM clojure.tools.logging$eval175$fn__178 invoke
INFO: Reference thread starting
Nov 19, 2020 3:08:58 PM clojure.tools.logging$eval175$fn__178 invoke
INFO: Library python3.6m found at [:system "python3.6m"]
Nov 19, 2020 3:08:58 PM clojure.tools.logging$eval175$fn__178 invoke
INFO: Library c found at [:system "c"]
Nov 19, 2020 3:09:02 PM clojure.tools.logging$eval147$fn__150 invoke
INFO: Executing python initialize with options:{:python-executable nil, :program-name nil, :python-home nil, :library-path nil}
Nov 19, 2020 3:09:02 PM clojure.tools.logging$eval147$fn__150 invoke
INFO: Detecting startup-info for Python executable:
Nov 19, 2020 3:09:02 PM clojure.tools.logging$eval147$fn__150 invoke
INFO: Startup info detected: {:python-home "/home/user/miniconda3/envs/usr", :lib-version "3.6", :libname "python3.6m", :java-library-path-addendum "/home/user/miniconda3/envs/usr/lib"}
Nov 19, 2020 3:09:02 PM clojure.tools.logging$eval147$fn__150 invoke
INFO: Setting java library path: /home/user/miniconda3/envs/usr/lib:/home/user/catkin_ws/devel/lib:/opt/ros/melodic/lib:/usr/java/packages/lib:/usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib
Nov 19, 2020 3:09:02 PM clojure.tools.logging$eval147$fn__150 invoke
INFO: Reference thread starting
Nov 19, 2020 3:09:02 PM clojure.tools.logging$eval147$fn__150 invoke
INFO: Library python3.6m found at [:system "python3.6m"]
Nov 19, 2020 3:09:02 PM clojure.tools.logging$eval147$fn__150 invoke
INFO: Library c found at [:system "c"]
Syntax error (NullPointerException) compiling at (/tmp/form-init6713682379458716776.clj:1:73).
null
Full report at:
/tmp/clojure-10025123200951564818.edn
Subprocess failed
REPL server launch timed out.
Full report:
{:clojure.main/message
"Syntax error (NullPointerException) compiling at (/tmp/form-init6713682379458716776.clj:1:73).\nnull\n",
:clojure.main/triage
{:clojure.error/phase :compile-syntax-check,
:clojure.error/line 1,
:clojure.error/column 73,
:clojure.error/source "form-init6713682379458716776.clj",
:clojure.error/path "/tmp/form-init6713682379458716776.clj",
:clojure.error/class java.lang.NullPointerException},
:clojure.main/trace
{:via
[{:type clojure.lang.Compiler$CompilerException,
:message
"Syntax error compiling at (/tmp/form-init6713682379458716776.clj:1:73).",
:data
{:clojure.error/phase :compile-syntax-check,
:clojure.error/line 1,
:clojure.error/column 73,
:clojure.error/source "/tmp/form-init6713682379458716776.clj"},
:at [clojure.lang.Compiler load "Compiler.java" 7648]}
{:type java.lang.ExceptionInInitializerError,
:at [java.lang.Class forName0 "Class.java" -2]}
{:type java.lang.NullPointerException,
:at [clojure.core$alias invokeStatic "core.clj" 4272]}],
:trace
[[clojure.core$alias invokeStatic "core.clj" 4272]
[clojure.core$load_lib invokeStatic "core.clj" 5958]
[clojure.core$load_lib doInvoke "core.clj" 5928]
[clojure.lang.RestFn applyTo "RestFn.java" 142]
[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core$load_libs invokeStatic "core.clj" 5985]
[clojure.core$load_libs doInvoke "core.clj" 5969]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core$require invokeStatic "core.clj" 6007]
[clojure.core$require doInvoke "core.clj" 6007]
[clojure.lang.RestFn invoke "RestFn.java" 436]
[proj.anchoring__init load nil 4]
[proj.anchoring__init <clinit> nil -1]
[java.lang.Class forName0 "Class.java" -2]
[java.lang.Class forName "Class.java" 398]
[clojure.lang.RT classForName "RT.java" 2211]
[clojure.lang.RT classForName "RT.java" 2220]
[clojure.lang.RT loadClassForName "RT.java" 2239]
[clojure.lang.RT load "RT.java" 449]
[clojure.lang.RT load "RT.java" 424]
[clojure.core$load$fn__6839 invoke "core.clj" 6126]
[clojure.core$load invokeStatic "core.clj" 6125]
[clojure.core$load doInvoke "core.clj" 6109]
[clojure.lang.RestFn invoke "RestFn.java" 408]
[proj.core__init load nil 47]
[proj.core__init <clinit> nil -1]
[java.lang.Class forName0 "Class.java" -2]
[java.lang.Class forName "Class.java" 398]
[clojure.lang.RT classForName "RT.java" 2211]
[clojure.lang.RT classForName "RT.java" 2220]
[clojure.lang.RT loadClassForName "RT.java" 2239]
[clojure.lang.RT load "RT.java" 449]
[clojure.lang.RT load "RT.java" 424]
[clojure.core$load$fn__6839 invoke "core.clj" 6126]
[clojure.core$load invokeStatic "core.clj" 6125]
[clojure.core$load doInvoke "core.clj" 6109]
[clojure.lang.RestFn invoke "RestFn.java" 408]
[clojure.core$load_one invokeStatic "core.clj" 5908]
[clojure.core$load_one invoke "core.clj" 5903]
[clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
[clojure.core$load_lib invokeStatic "core.clj" 5947]
[clojure.core$load_lib doInvoke "core.clj" 5928]
[clojure.lang.RestFn applyTo "RestFn.java" 142]
[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core$load_libs invokeStatic "core.clj" 5985]
[clojure.core$load_libs doInvoke "core.clj" 5969]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core$require invokeStatic "core.clj" 6007]
[clojure.core$require doInvoke "core.clj" 6007]
[clojure.lang.RestFn invoke "RestFn.java" 408]
[user$eval5 invokeStatic "form-init6713682379458716776.clj" 1]
[user$eval5 invoke "form-init6713682379458716776.clj" 1]
[clojure.lang.Compiler eval "Compiler.java" 7177]
[clojure.lang.Compiler eval "Compiler.java" 7166]
[clojure.lang.Compiler eval "Compiler.java" 7166]
[clojure.lang.Compiler load "Compiler.java" 7636]
[clojure.lang.Compiler loadFile "Compiler.java" 7574]
[clojure.main$load_script invokeStatic "main.clj" 475]
[clojure.main$init_opt invokeStatic "main.clj" 477]
[clojure.main$init_opt invoke "main.clj" 477]
[clojure.main$initialize invokeStatic "main.clj" 508]
[clojure.main$null_opt invokeStatic "main.clj" 542]
[clojure.main$null_opt invoke "main.clj" 539]
[clojure.main$main invokeStatic "main.clj" 664]
[clojure.main$main doInvoke "main.clj" 616]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.lang.Var applyTo "Var.java" 705]
[clojure.main main "main.java" 40]],
:phase :compile-syntax-check}}
Related
how's it going?
My code can be found HERE
I've been trying to learn Clojure by following a guide, but I'm not quite sure why this piece of code isn't working.
Here's the code:
(ns calc-api.server.server
(:require [ring.adapter.jetty :as jetty]
[ring.middleware.params :as params]
[ring.util.http-response :as response]
[reitit.ring.middleware.muuntaja :as muuntaja]
[muuntaja.core :as m]
[reitit.ring.coercion :as coercion]
[reitit.ring :as ring]))
(def hello-routes
["/hello" {:get {:handler (fn [_]
(response/ok {:mesage "Hello Reitit!"}))}}])
(def app
(ring/ring-handler
(ring/router
[hello-routes]
{:data {:muuntaja m/instance
:middleware [params/wrap-params
muuntaja/format-middleware
coercion/coerce-exceptions-middleware
coercion/coerce-request-middleware
coercion/coerce-response-middleware]}})
(ring/create-default-handler)))
(defonce running-server (atom nil))
(defn start
[]
(when (nil? #running-server)
(reset! running-server (jetty/run-jetty #'app {:port 3000
:join? false})))
(println "Server running in port 3000"))
(defn stop
[]
(when-not (nil? #running-server)
(.stop #running-server)
(reset! running-server nil))
(println "Server stopped"))
When I run the REPL and swap over to the calc-api namespace and run the (start) function:
lein repl
(in-ns 'calc-api.server.server)
(start)
I was expecting the server to run and print the "server is running on port x", but here's the outcome:
Syntax error compiling at (/tmp/form-init2855747266943058886.clj:1:1).
Unable to resolve symbol: start in this context
Any ideas on why this is happening? All help is very much appreciated.
EDIT[1]
Following Alan Thompson's suggestion, here's what happened:
Copied my code and dependencies to the template's folder, running lein clean + lein run results in
{:clojure.main/message
"Syntax error compiling at (demo/core.clj:50:3).\nNo such namespace: log\n",
:clojure.main/triage
{:clojure.error/phase :compile-syntax-check,
:clojure.error/line 50,
:clojure.error/column 3,
:clojure.error/source "core.clj",
:clojure.error/path "demo/core.clj",
:clojure.error/class java.lang.RuntimeException,
:clojure.error/cause "No such namespace: log"},
:clojure.main/trace
{:via
[{:type clojure.lang.Compiler$CompilerException,
:message "Syntax error compiling at (demo/core.clj:50:3).",
:data
{:clojure.error/phase :compile-syntax-check,
:clojure.error/line 50,
:clojure.error/column 3,
:clojure.error/source "demo/core.clj"},
:at [clojure.lang.Compiler analyze "Compiler.java" 6812]}
{:type java.lang.RuntimeException,
:message "No such namespace: log",
:at [clojure.lang.Util runtimeException "Util.java" 221]}],
:trace
[[clojure.lang.Util runtimeException "Util.java" 221]
[clojure.lang.Compiler resolveIn "Compiler.java" 7388]
[clojure.lang.Compiler resolve "Compiler.java" 7362]
[clojure.lang.Compiler analyzeSymbol "Compiler.java" 7323]
[clojure.lang.Compiler analyze "Compiler.java" 6772]
[clojure.lang.Compiler analyze "Compiler.java" 6749]
[clojure.lang.Compiler$InvokeExpr parse "Compiler.java" 3824]
[clojure.lang.Compiler analyzeSeq "Compiler.java" 7113]
[clojure.lang.Compiler analyze "Compiler.java" 6793]
[clojure.lang.Compiler analyze "Compiler.java" 6749]
[clojure.lang.Compiler$BodyExpr$Parser parse "Compiler.java" 6122]
[clojure.lang.Compiler$FnMethod parse "Compiler.java" 5471]
[clojure.lang.Compiler$FnExpr parse "Compiler.java" 4033]
[clojure.lang.Compiler analyzeSeq "Compiler.java" 7109]
[clojure.lang.Compiler analyze "Compiler.java" 6793]
[clojure.lang.Compiler analyzeSeq "Compiler.java" 7099]
[clojure.lang.Compiler analyze "Compiler.java" 6793]
[clojure.lang.Compiler access$300 "Compiler.java" 38]
[clojure.lang.Compiler$DefExpr$Parser parse "Compiler.java" 596]
[clojure.lang.Compiler analyzeSeq "Compiler.java" 7111]
[clojure.lang.Compiler analyze "Compiler.java" 6793]
[clojure.lang.Compiler analyze "Compiler.java" 6749]
[clojure.lang.Compiler eval "Compiler.java" 7185]
[clojure.lang.Compiler load "Compiler.java" 7640]
[clojure.lang.RT loadResourceScript "RT.java" 381]
[clojure.lang.RT loadResourceScript "RT.java" 372]
[clojure.lang.RT load "RT.java" 459]
[clojure.lang.RT load "RT.java" 424]
[clojure.core$load$fn__6856 invoke "core.clj" 6115]
[clojure.core$load invokeStatic "core.clj" 6114]
[clojure.core$load doInvoke "core.clj" 6098]
[clojure.lang.RestFn invoke "RestFn.java" 408]
[clojure.core$load_one invokeStatic "core.clj" 5897]
[clojure.core$load_one invoke "core.clj" 5892]
[clojure.core$load_lib$fn__6796 invoke "core.clj" 5937]
[clojure.core$load_lib invokeStatic "core.clj" 5936]
[clojure.core$load_lib doInvoke "core.clj" 5917]
[clojure.lang.RestFn applyTo "RestFn.java" 142]
[clojure.core$apply invokeStatic "core.clj" 669]
[clojure.core$load_libs invokeStatic "core.clj" 5974]
[clojure.core$load_libs doInvoke "core.clj" 5958]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.core$apply invokeStatic "core.clj" 669]
[clojure.core$require invokeStatic "core.clj" 5996]
[clojure.core$require doInvoke "core.clj" 5996]
[clojure.lang.RestFn invoke "RestFn.java" 408]
[user$eval142$fn__146 invoke "form-init13165779102252361276.clj" 1]
[user$eval142 invokeStatic "form-init13165779102252361276.clj" 1]
[user$eval142 invoke "form-init13165779102252361276.clj" 1]
[clojure.lang.Compiler eval "Compiler.java" 7181]
[clojure.lang.Compiler eval "Compiler.java" 7171]
[clojure.lang.Compiler load "Compiler.java" 7640]
[clojure.lang.Compiler loadFile "Compiler.java" 7578]
[clojure.main$load_script invokeStatic "main.clj" 475]
[clojure.main$init_opt invokeStatic "main.clj" 477]
[clojure.main$init_opt invoke "main.clj" 477]
[clojure.main$initialize invokeStatic "main.clj" 508]
[clojure.main$null_opt invokeStatic "main.clj" 542]
[clojure.main$null_opt invoke "main.clj" 539]
[clojure.main$main invokeStatic "main.clj" 664]
[clojure.main$main doInvoke "main.clj" 616]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.lang.Var applyTo "Var.java" 705]
[clojure.main main "main.java" 40]],
:cause "No such namespace: log",
:phase :compile-syntax-check}}
Which I don't think has to do anything with my original code?
EDIT[2]
I've found a solution which I don't like but works for my learning purposes. I changed the core.clj file to require the server namespace and call the start function from there.
(ns calc-api.core
(:gen-class))
(require '[calc-api.server.server :as calc-api-server])
(defn -main
"I don't do a whole lot ... yet."
[& args]
(calc-api-server/start))
Which means I have to cmd+d every time I want to stop the server, but at least it works. Thanks for all the help provided.
Your problem is difficult to diagnose with only the repl information & error. As an expedient, I would suggest starting with a known working template project.
Do a git clone as the README describes, then lein clean; lein test to verify the install (& your java, etc) are configured correctly.
At that point, copy your code into src/clj/demo/core.clj and then try lein clean; lein run. Even if it doesn't work, you will get a much more detailed error message, including usable line numbers for any error.
Please update your question with the results of this experiment.
I'm new to Clojure, trying to debug my program with the function trace.
I tried this in REPL:
(require '[clojure.tools.trace :as trace])
But it throws an exception:
Execution error (FileNotFoundException) at user/eval199 (REPL:1).
Could not locate clojure/tools/trace__init.class, clojure/tools/trace.clj or clojure/tools/trace.cljc on classpath.
*e says this:
#error {
:cause "Could not locate clojure/tools/trace__init.class, clojure/tools/trace.clj or clojure/tools/trace.cljc on classpath."
:via
[{:type java.io.FileNotFoundException
:message "Could not locate clojure/tools/trace__init.class, clojure/tools/trace.clj or clojure/tools/trace.cljc on classpath."
:at [clojure.lang.RT load "RT.java" 462]}]
:trace
[[clojure.lang.RT load "RT.java" 462]
[clojure.lang.RT load "RT.java" 424]
[clojure.core$load$fn__6839 invoke "core.clj" 6126]
[clojure.core$load invokeStatic "core.clj" 6125]
[clojure.core$load doInvoke "core.clj" 6109]
[clojure.lang.RestFn invoke "RestFn.java" 408]
[clojure.core$load_one invokeStatic "core.clj" 5908]
[clojure.core$load_one invoke "core.clj" 5903]
[clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
[clojure.core$load_lib invokeStatic "core.clj" 5947]
[clojure.core$load_lib doInvoke "core.clj" 5928]
[clojure.lang.RestFn applyTo "RestFn.java" 142]
[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core$load_libs invokeStatic "core.clj" 5985]
[clojure.core$load_libs doInvoke "core.clj" 5969]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core$require invokeStatic "core.clj" 6007]
[clojure.core$require doInvoke "core.clj" 6007]
[clojure.lang.RestFn invoke "RestFn.java" 408]
[user$eval193 invokeStatic "NO_SOURCE_FILE" 1]
[user$eval193 invoke "NO_SOURCE_FILE" 1]
[clojure.lang.Compiler eval "Compiler.java" 7177]
[clojure.lang.Compiler eval "Compiler.java" 7132]
[clojure.core$eval invokeStatic "core.clj" 3214]
[clojure.core$eval invoke "core.clj" 3210]
[clojure.main$repl$read_eval_print__9086$fn__9089 invoke "main.clj" 437]
[clojure.main$repl$read_eval_print__9086 invoke "main.clj" 437]
[clojure.main$repl$fn__9095 invoke "main.clj" 458]
[clojure.main$repl invokeStatic "main.clj" 458]
[clojure.main$repl_opt invokeStatic "main.clj" 522]
[clojure.main$main invokeStatic "main.clj" 667]
[clojure.main$main doInvoke "main.clj" 616]
[clojure.lang.RestFn invoke "RestFn.java" 397]
[clojure.lang.AFn applyToHelper "AFn.java" 152]
[clojure.lang.RestFn applyTo "RestFn.java" 132]
[clojure.lang.Var applyTo "Var.java" 705]
[clojure.main main "main.java" 40]]}
I've searched for the docs of clojure.tools.trace on Github.
It says you need import dependency, but the dependency information are for Clojure CLI, Leiningen or Maven, not for REPL in clojure.
(When I'm saying REPL in clojure, I actually mean clj, sorry for the vague description)
So I stuck here. Can anyone tell me how to fix this and what' happenning?
Since you're using clj (the Clojure CLI), you'll need to add the clojure.tools.trace library to your deps.edn file:
seanc#DESKTOP-30ICA76:~/clojure$ mkdir lyhokia
seanc#DESKTOP-30ICA76:~/clojure$ cd lyhokia/
seanc#DESKTOP-30ICA76:~/clojure/lyhokia$ vi deps.edn
<add the library>
seanc#DESKTOP-30ICA76:~/clojure/lyhokia$ cat deps.edn
{:deps {org.clojure/tools.trace {:mvn/version "0.7.10"}}}
seanc#DESKTOP-30ICA76:~/clojure/lyhokia$ clj
Clojure 1.10.1
user=> (require '[clojure.tools.trace :as trace])
nil
user=> (trace/trace (* 1 2 3))
TRACE: 6
6
user=>
If you are using Leiningen, be sure your project.clj has a line in it like:
[org.clojure/tools.trace "0.7.10"]
under the :dependencies key. Then it will work:
> lein repl
Java HotSpot(TM) 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
nREPL server started on port 38715 on host 127.0.0.1 - nrepl://127.0.0.1:38715
REPL-y 0.4.3, nREPL 0.6.0
Clojure 1.10.2-alpha1
demo.core=> (require '[clojure.tools.trace :as trace])
nil
See the clojure.tools.trace GitHub page for information on other dependency formats.
I always start out a new Clojure project by cloning this Clojure template project from git, then adding my changes to project.clj, etc. You can then type lein repl to start up a repl session.
I'm trying to create a simple Clojure app to parse stdin and execute some commands accordingly. I created a new leiningen project with lein new app myproject and added my code to src/myproject/core.clj :
(ns myproject.core
(:require [clojure.string :as str])
(:gen-class))
(def global-vector (ref [{:name "Bob" :age 22} {:name "Alice" :age 21}]))
(defn call [fn_name & fn_args]
(apply (resolve (symbol fn_name)) (map keyword fn_args)))
(defn select
[key]
(dosync
(map #(get % key) #global-vector)))
(defn -main []
(while true
(let [[command cargs] (str/split (read-line) #" ")]
(println (call command cargs)))))
To be explicit here are the steps to reproduce what I'm trying to do:
I want to run this program from command line (currently I use lein run)
It should wait for user input (I use the read-line function)
I enter some text: select name
I expect the program to print the names stored in global-vector but it crashes with a NPE instead
Everything seems to work as expected when ran with lein repl:
myproject.core=> (select :name)
("Bob" "Alice")
myproject.core=> (apply select [:name])
("Bob" "Alice")
myproject.core=> (call "select" "name")
("Bob" "Alice")
myproject.core=> (let [[a b] (str/split "select name" #" ")]
#_=> (println (call a b)))
(Bob Alice)
nil
myproject.core=> (-main)
select name
(Bob Alice)
But when I run it with lein run and enter some input I get a NullPointerException:
$lein run
select name
Syntax error (NullPointerException) compiling at (/private/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/form-init2363625704485841211.clj:1:125).
null
Full report at:
/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/clojure-6381054570172229346.edn
Here is the content of the report file:
{:clojure.main/message
"Syntax error (NullPointerException) compiling at (/private/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/form-init2363625704485841211.clj:1:125).\nnull\n",
:clojure.main/triage
{:clojure.error/phase :compile-syntax-check,
:clojure.error/line 1,
:clojure.error/column 125,
:clojure.error/source "form-init2363625704485841211.clj",
:clojure.error/path
"/private/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/form-init2363625704485841211.clj",
:clojure.error/class java.lang.NullPointerException},
:clojure.main/trace
{:via
[{:type clojure.lang.Compiler$CompilerException,
:message
"Syntax error compiling at (/private/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/form-init2363625704485841211.clj:1:125).",
:data
{:clojure.error/phase :compile-syntax-check,
:clojure.error/line 1,
:clojure.error/column 125,
:clojure.error/source
"/private/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/form-init2363625704485841211.clj"},
:at [clojure.lang.Compiler load "Compiler.java" 7648]}
{:type java.lang.NullPointerException,
:at [clojure.core$apply invokeStatic "core.clj" 665]}],
:trace
[[clojure.core$apply invokeStatic "core.clj" 665]
[clojure.core$apply invoke "core.clj" 660]
[myproject.core$call invokeStatic "core.clj" 8]
[myproject.core$call doInvoke "core.clj" 7]
[clojure.lang.RestFn invoke "RestFn.java" 423]
[myproject.core$_main invokeStatic "core.clj" 18]
[myproject.core$_main invoke "core.clj" 15]
[clojure.lang.Var invoke "Var.java" 380]
[user$eval140 invokeStatic "form-init2363625704485841211.clj" 1]
[user$eval140 invoke "form-init2363625704485841211.clj" 1]
[clojure.lang.Compiler eval "Compiler.java" 7177]
[clojure.lang.Compiler eval "Compiler.java" 7167]
[clojure.lang.Compiler load "Compiler.java" 7636]
[clojure.lang.Compiler loadFile "Compiler.java" 7574]
[clojure.main$load_script invokeStatic "main.clj" 475]
[clojure.main$init_opt invokeStatic "main.clj" 477]
[clojure.main$init_opt invoke "main.clj" 477]
[clojure.main$initialize invokeStatic "main.clj" 508]
[clojure.main$null_opt invokeStatic "main.clj" 542]
[clojure.main$null_opt invoke "main.clj" 539]
[clojure.main$main invokeStatic "main.clj" 664]
[clojure.main$main doInvoke "main.clj" 616]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.lang.Var applyTo "Var.java" 705]
[clojure.main main "main.java" 40]],
:phase :compile-syntax-check}}
I'm trying to understand the traceback but I lack familiarity with the Clojure/Java environment and it's indecipherable so far. What's being called on a Null value exactly? Is it because global-vector is defined outside of main? (But why does it work in Repl then?)
I use Clojure version: 1.10.1.739 and Leiningen 2.9.4 on Java 11.0.2 OpenJDK 64-Bit Server VM.
After further investigation I found that it has to do with namespace resolution. The following expression:
(resolve (symbol fn_name))
works in Repl but return nil when executed from "lein run", which in turn causes the apply function to raise a NullPointerException.
The symbol function can be passed a ns parameter so I fixed it by hardcoding my current namespace like this:
(resolve (symbol "myproject.core" fn_name))
I have added a dependency to Distributions https://clojars.org/distributions
:dependencies [[org.clojure/clojure "1.10.1"]
[distributions "0.1.2"]]
when I add a require
(ns simulator.core
(:require [distributions.core :refer :all]))
and do lein run. It goes nuts. It tries to find a different distributions package (one from Incanter, but I have not referenced incanter anywhere).
Syntax error (FileNotFoundException) compiling at (distributions/core.clj:1:1).
Could not locate incanter/charts__init.class, incanter/charts.clj or incanter/charts.cljc on classpath.
If I look at the source code https://github.com/michaellindon/distributions there is no reference to Incanter. Where does this Incanter come from? How do I telll clojure this is not the dependency I'm looking for.
The dependency tree looks clean:
[clojure-complete "0.2.5" :exclusions [[org.clojure/clojure]]]
[distributions "0.1.2"]
[net.mikera/core.matrix "0.57.0"]
[org.clojure/tools.macro "0.1.5"]
[net.mikera/vectorz-clj "0.45.0"]
[net.mikera/clojure-utils "0.7.0"]
[net.mikera/vectorz "0.63.0"]
[net.mikera/mathz "0.3.0"]
[net.mikera/randomz "0.3.0"]
[us.bpsm/edn-java "0.4.6"]
[org.apache.commons/commons-math3 "3.6.1"]
[nrepl "0.7.0" :exclusions [[org.clojure/clojure]]]
[org.clojure/clojure "1.10.1"]
[org.clojure/core.specs.alpha "0.2.44"]
[org.clojure/spec.alpha "0.2.176"]
No incanter in sight.
If I add Incanter
:dependencies [[org.clojure/clojure "1.10.1"]
[distributions "0.1.2"]
[incanter/incanter-charts "1.9.3"]]
I get
Syntax error (ClassNotFoundException) compiling at (bid_simulator/core.clj:2:3).
distributions.core
:clojure.main/message
"Syntax error (ClassNotFoundException) compiling at (bid_simulator/core.clj:2:3).\ndistributions.core\n",
:clojure.main/triage
{:clojure.error/phase :compile-syntax-check,
:clojure.error/line 2,
:clojure.error/column 3,
:clojure.error/source "core.clj",
:clojure.error/path "bid_simulator/core.clj",
:clojure.error/class java.lang.ClassNotFoundException,
:clojure.error/cause "distributions.core"},
:clojure.main/trace
{:via
[{:type clojure.lang.Compiler$CompilerException,
:message "Syntax error compiling at (bid_simulator/core.clj:2:3).",
:data
{:clojure.error/phase :compile-syntax-check,
:clojure.error/line 2,
:clojure.error/column 3,
:clojure.error/source "bid_simulator/core.clj"},
:at [clojure.lang.Compiler analyze "Compiler.java" 6808]}
{:type java.lang.ClassNotFoundException,
:message "distributions.core",
:at
[java.net.URLClassLoader findClass "URLClassLoader.java" 435]}],
:trace
[[java.net.URLClassLoader findClass "URLClassLoader.java" 435]
[clojure.lang.DynamicClassLoader
findClass
"DynamicClassLoader.java"
69]
[java.lang.ClassLoader loadClass "ClassLoader.java" 589]
[clojure.lang.DynamicClassLoader
loadClass
"DynamicClassLoader.java"
77]
[java.lang.ClassLoader loadClass "ClassLoader.java" 522]
[java.lang.Class forName0 "Class.java" -2]
[java.lang.Class forName "Class.java" 427]
[clojure.lang.RT classForName "RT.java" 2211]
[clojure.lang.RT classForName "RT.java" 2220]
[clojure.lang.Compiler resolveIn "Compiler.java" 7395]
[clojure.lang.Compiler resolve "Compiler.java" 7358]
[clojure.lang.Compiler analyzeSymbol "Compiler.java" 7319]
[clojure.lang.Compiler analyze "Compiler.java" 6768]
[clojure.lang.Compiler analyze "Compiler.java" 6745]
[clojure.lang.Compiler$VectorExpr parse "Compiler.java" 3260]
[clojure.lang.Compiler analyze "Compiler.java" 6791]
[clojure.lang.Compiler analyze "Compiler.java" 6745]
[clojure.lang.Compiler$InvokeExpr parse "Compiler.java" 3881]
[clojure.lang.Compiler analyzeSeq "Compiler.java" 7109]
[clojure.lang.Compiler analyze "Compiler.java" 6789]
[clojure.lang.Compiler analyze "Compiler.java" 6745]
[clojure.lang.Compiler$BodyExpr$Parser parse "Compiler.java" 6120]
[clojure.lang.Compiler$FnMethod parse "Compiler.java" 5467]
[clojure.lang.Compiler$FnExpr parse "Compiler.java" 4029]
[clojure.lang.Compiler analyzeSeq "Compiler.java" 7105]
[clojure.lang.Compiler analyze "Compiler.java" 6789]
[clojure.lang.Compiler eval "Compiler.java" 7174]
[clojure.lang.Compiler load "Compiler.java" 7636]
[clojure.lang.RT loadResourceScript "RT.java" 381]
[clojure.lang.RT loadResourceScript "RT.java" 372]
[clojure.lang.RT load "RT.java" 459]
[clojure.lang.RT load "RT.java" 424]
[clojure.core$load$fn__6839 invoke "core.clj" 6126]
[clojure.core$load invokeStatic "core.clj" 6125]
[clojure.core$load doInvoke "core.clj" 6109]
[clojure.lang.RestFn invoke "RestFn.java" 408]
[clojure.core$load_one invokeStatic "core.clj" 5908]
[clojure.core$load_one invoke "core.clj" 5903]
[clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
[clojure.core$load_lib invokeStatic "core.clj" 5947]
[clojure.core$load_lib doInvoke "core.clj" 5928]
[clojure.lang.RestFn applyTo "RestFn.java" 142]
[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core$load_libs invokeStatic "core.clj" 5985]
[clojure.core$load_libs doInvoke "core.clj" 5969]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.core$apply invokeStatic "core.clj" 667]
[clojure.core$require invokeStatic "core.clj" 6007]
[clojure.core$require doInvoke "core.clj" 6007]
[clojure.lang.RestFn invoke "RestFn.java" 408]
[user$eval140$fn__144 invoke "form-init1507618823433517384.clj" 1]
[user$eval140 invokeStatic "form-init1507618823433517384.clj" 1]
[user$eval140 invoke "form-init1507618823433517384.clj" 1]
[clojure.lang.Compiler eval "Compiler.java" 7177]
[clojure.lang.Compiler eval "Compiler.java" 7167]
[clojure.lang.Compiler load "Compiler.java" 7636]
[clojure.lang.Compiler loadFile "Compiler.java" 7574]
[clojure.main$load_script invokeStatic "main.clj" 475]
[clojure.main$init_opt invokeStatic "main.clj" 477]
[clojure.main$init_opt invoke "main.clj" 477]
[clojure.main$initialize invokeStatic "main.clj" 508]
[clojure.main$null_opt invokeStatic "main.clj" 542]
[clojure.main$null_opt invoke "main.clj" 539]
[clojure.main$main invokeStatic "main.clj" 664]
[clojure.main$main doInvoke "main.clj" 616]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.lang.Var applyTo "Var.java" 705]
[clojure.main main "main.java" 40]],
:cause "distributions.core",
:phase :compile-syntax-check}}
Update: the error cleared up by adding Incanter in a clean new project.
The require was there in around the 0.1.2-SNAPSHOT time: https://github.com/michaellindon/distributions/blob/b6f18679be45617ff91ab362d1991061b3b84277/src/distributions/core.clj#L5
But the project at that point in time did not have a transitive dependency set for incanter.
The easiest way to make sure would be to open the jar (you can find that with e.g. lein cp) and have a look.
At that point you might just want to add incater as a dependency yourself to your project.
I would like to be able to json encode an exception object. I am pushing my logs to sumologic and would like to be able to push json encoded exception's so that I can parse and filter these logs in sumo too.
However, I can't json encode the exception and get this error:
Cannot JSON encode object of class: class java.lang.Class: class clojure.lang.ExceptionInfo
Here is my exception handler for compojure-api:
(defn exception-handler
"Handles exceptions."
[f]
(fn [^Exception ex data request]
(log/error (json/generate-string {:request-id log-helper/*request-id*
:error ex}))
(f (.getMessage ex))))
Applications will have different needs in this regards, but one strategy can be to use Throwable->map:
(Throwable->map
(ex-info
"The Holy Grail me be found in the castle of-aaaaaaaaaaaaaaaarrrgh"
{:film "Monty Python and the Holy Grail (1975)"}
(IllegalStateException. "aaaaargh")))
=>
{:cause "aaaaargh",
:via
[{:type clojure.lang.ExceptionInfo,
:message
"The Holy Grail me be found in the castle of-aaaaaaaaaaaaaaaarrrgh",
:data {:film "Monty Python and the Holy Grail (1975)"},
:at [clojure.core$ex_info invokeStatic "core.clj" 4739]}
{:type java.lang.IllegalStateException,
:message "aaaaargh",
:at [user$eval13 invokeStatic "NO_SOURCE_FILE" 2]}],
:trace
[[user$eval13 invokeStatic "NO_SOURCE_FILE" 2]
[user$eval13 invoke "NO_SOURCE_FILE" 2]
[clojure.lang.Compiler eval "Compiler.java" 7062]
[clojure.lang.Compiler eval "Compiler.java" 7025]
[clojure.core$eval invokeStatic "core.clj" 3206]
[clojure.core$eval invoke "core.clj" 3202]
[clojure.main$repl$read_eval_print__8572$fn__8575
invoke
"main.clj"
243]
[clojure.main$repl$read_eval_print__8572 invoke "main.clj" 243]
[clojure.main$repl$fn__8581 invoke "main.clj" 261]
[clojure.main$repl invokeStatic "main.clj" 261]
[clojure.main$repl_opt invokeStatic "main.clj" 325]
[clojure.main$main invokeStatic "main.clj" 424]
[clojure.main$main doInvoke "main.clj" 387]
[clojure.lang.RestFn invoke "RestFn.java" 397]
[clojure.lang.AFn applyToHelper "AFn.java" 152]
[clojure.lang.RestFn applyTo "RestFn.java" 132]
[clojure.lang.Var applyTo "Var.java" 702]
[clojure.main main "main.java" 37]]}
If you want to make a custom data representation of Exceptions, I recommend you have a look at the source of Throwable->map to know how to fetch the relevant information.