I am very new to clojure and I get the following error:
Caused by: java.lang.IllegalStateException: Attempting to call unbound fn: #'datoteka.core/to-file
at clojure.lang.Var$Unbound.throwArity(Var.java:45)
at clojure.lang.AFn.invoke(AFn.java:32)
at package.auth_monitor$start_monitor_thread.invokeStatic(auth_monitor.clj:43)
at package.auth_monitor$start_monitor_thread.invoke(auth_monitor.clj:38)
at package.auth_monitor$start_monitor.invokeStatic(auth_monitor.clj:62)
at package.auth_monitor$start_monitor.invoke(auth_monitor.clj:49)
at package.auth_monitor$fn__11768.invokeStatic(auth_monitor.clj:71)
at package.auth_monitor$fn__11768.invoke(auth_monitor.clj:70)
the code is:
42. (let [^TailerListener listener (make-listener)
43. ^File file (fs/to-file path)
44. ^Tailer tailer (Tailer. file listener 1000 true)]
45. (doto (Thread. tailer)
46. (.setDaemon false)
47. (.start)))
I presume you are using the Datoteka library. Try using the file function to get a File object based on the path (to-file seems to be a wrong name):
(let [^TailerListener listener (make-listener)
^File file (fs/file path)
^Tailer tailer (Tailer. file listener 1000 true)]
(doto (Thread. tailer)
(.setDaemon false)
(.start)))
Related
I'm trying to run clojure.core.server/start-server but instead of using the repl I want a custom function as accept option. I'm following this post where a repl server is executed as
clojure -X clojure.core.server/start-server :name '"server"' :port 5555 :accept clojure.core.server/repl :server-daemon false
What requirements do I need to pass a function to accept opt? What if I only want to print the request from any connection? Using something like clojure.core/println didn't work
clojure -X clojure.core.server/start-server :name '"server"' :port 5555 :accept clojure.core/println :server-daemon false
btw, I can't even run start-server on the repl itself, I've got the error everytime a made a request. Is it possible to run it from the repl?
(clojure.core.server/start-server {:name "server" :port 9000 :accept clojure.core.server/repl :server-daemon false})
#object[java.net.ServerSocket 0x25b865b5 "ServerSocket[addr=localhost/127.0.0.1,localport=9000]"]
user=> Exception in thread "Clojure Connection server 1" java.lang.ClassCastException: class clojure.core.server$repl cannot be cast to class clojure.lang.Named (clojure.core.server$repl and clojure.lang.Named are in unnamed module of loader 'app')
at clojure.core$namespace.invokeStatic(core.clj:1612)
at clojure.core.server$accept_connection.invokeStatic(server.clj:73)
at clojure.core.server$start_server$fn__8998$fn__8999$fn__9001.invoke(server.clj:117)
at clojure.lang.AFn.run(AFn.java:22)
at java.base/java.lang.Thread.run(Thread.java:833)
The start-server function states, that :accept must be a namespaced
symbol (so this is the reason, why you see the error in your REPL
(you are passing a variable; use 'clojure.core/println instead --
note the leading ').
As for passing your own function, it helps to take a look at the
function clojure.core.server/accept-connection, what is actually going
on. So basically your :accept function gets called with *in*,
*out*, *err* redirected (and also a binding of *session* with some
book-keeping) and the :args. So you want to read/write on
stdin/stdout in your function and parameterize with the given arguments.
E.g. create a file src/so.clj with the following content:
(ns so)
(defn accept
[prefix]
(loop []
(println prefix (read-line))
(recur)))
Then start the server from the same root:
clojure -X clojure.core.server/start-server :name '"server"' :port 5555 \
:accept so/accept \
:args '[">>>"]' \
:server-daemon false
Note the :accept symbol (it's coming from the shell, so Clojure reads
that as a symbol) points to the namespace and the function within. Make
sure, things match up with the class-path (src is a default source
path for the Clojure CLI).
Also note the passing of the :args represented as an EDN array.
Inside accept-connection the call to your function is then (apply accept args), so you can assume regular arguments in your accept-fn.
Then test your server with e.g. telnet:
% telnet localhost 5555
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello
>>> hello
world
>>> world
Following this response: Org-Mode - How do I create a new file with org-capture?
I am trying to make this piece of code work, but I get the error: invalid file location: nil.
(defun capture-report-data-file (path)
(let ((name (read-string "Name: ")))
(expand-file-name (format "%s-%s.txt"
(format-time-string "%Y-%m-%d")
name) path)))
'(("t"
"todo"
entry
(file (capture-report-date-file "~/path/path/name"))
"* TODO")))
Actually, it works like this:
Replace
(file (capture-report-date-file "~/path/path/name"))
with
(file (lambda () (capture-report-date-file "~/path/path/name")))
I'm an absolute Clojure beginner and I'm trying to build a CLI app using the clojure.tools.cli library.
My problem is that I can't show any error when an option is not provided with required parameter.
What I want:
$ java -jar test.jar -m SAMPLE
Given file: SAMPLE
$ java -jar test.jar -m
ERROR: Please provide a file
What happens:
$ java -jar test.jar -m SAMPLE
Given file: SAMPLE
$ java -jar test.jar -m
$
It doesn't show anything.
Here is my code:
(ns obmed-clj.core
(:require [clojure.tools.cli :refer [parse-opts]])
(:gen-class))
(def cli-options
[["-m" "--menu FILE" "Provide menu file path"
:parse-fn #(if (nil? %)
(println "ERROR: Please provide a file")
%)
:validate-fn #(println "Given file:" %)]])
(defn -main [& args]
(parse-opts args cli-options))
You are abusing the -fn arguments here a little. Their use is to convert the "string" (in your case, since you have "--menu FILE") and then do additional validation on that (but rather use :validate [fn msg] instead). So e.g.:
user=> (def cli-opts [["-m" "--menu FILE" "menu file"
:parse-fn #(java.io.File. %)
:validate [#(.exists %) "file must exist"]]])
#'user/cli-opts
Missing argument:
user=> (parse-opts ["-m"] cli-opts)
{:arguments [],
:errors ["Missing required argument for \"-m FILE\""],
:options {},
:summary " -m, --menu FILE menu file"}
File not existing:
user=> (parse-opts ["-m" "XXX"] cli-opts)
{:arguments [],
:errors ["Failed to validate \"-m XXX\": file must exist"],
:options {},
:summary " -m, --menu FILE menu file"}
All is well:
user=> (parse-opts ["-m" "/etc/hosts"] cli-opts)
{:arguments [],
:errors nil,
:options {:menu #<java.io.File#34d63c80 /etc/hosts>},
:summary " -m, --menu FILE menu file"}
I have a compojure route which returns a file. I want to test -
1) If a file is returned.
2) The specific file that was returned.
When I run (app (ring.mock/request :get "/myroute")) I get
{:body #<File resources/public/templates/index.html>, :headers {"Content-Length" "2349", "Last-Modified" "Sat, 16 Mar 2013 11:01:03 GMT"}, :status 200}
How do I check that the returned value in the body is of a type file ? And getting more ambitious can I check it is the file located at 'resources/public/templates/index.html' ?
Ring requests are just maps, so you can extract the body with the :body keyword and then check it's type with type
(type (:body (app (ring.mock/request :get "/myroute"))))
(perhaps I'm not understanding the question though?)
I'm trying to use an MPD library in Java in Clojure. Everything has gone well, but these methods that return a java.util.Collection get bad reception in REPL. Let's define
(def mpd (org.bff.javampd.MPD. "localhost" ))
(def pl (.getMPDPlaylist mpd))
(def db (.getMPDDatabase mpd))
And now some methods play ok:
(.getSongList pl) ; returns List<MPDSong>
works well. But for instance every db (MPDDatabase) method return Collection<MPDSong> (according to their API):
(.findAlbum db "Crises") ; returns Collection<MPDSong>
java.lang.ClassCastException (NO_SOURCE_FILE:0)
Doesn't work that well. Why is that, how to fix it?
Stack trace follows:
hello.hello=> (.findAlbum db "Crises")
java.lang.ClassCastException (NO_SOURCE_FILE:0)
hello.hello=> (.printStackTrace *e)
java.lang.ClassCastException (NO_SOURCE_FILE:0)
at clojure.lang.Compiler.eval(Compiler.java:5440)
at clojure.lang.Compiler.eval(Compiler.java:5391)
at clojure.core$eval.invoke(core.clj:2382)
at clojure.main$repl$read_eval_print__5624.invoke(main.clj:183)
at clojure.main$repl$fn__5629.invoke(main.clj:204)
at clojure.main$repl.doInvoke(main.clj:204)
at clojure.lang.RestFn.invoke(RestFn.java:422)
at user$eval13$acc__808__auto____14$fn__16.invoke(NO_SOURCE_FILE:1)
at clojure.lang.AFn.run(AFn.java:24)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.ClassCastException
at java.lang.Class.cast(Class.java:2990)
at clojure.lang.Reflector.boxArg(Reflector.java:364)
at clojure.lang.Reflector.boxArgs(Reflector.java:397)
at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:55)
at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:28)
at hello.hello$eval44.invoke(NO_SOURCE_FILE:8)
at clojure.lang.Compiler.eval(Compiler.java:5424)
... 9 more
nil
Looks like the API Documentation is invalid (checking using clojure.contrib.repl-utils):
user> (show MPDDatabase "findAlbum$")
=== public org.bff.javampd.MPDDatabase ===
[ 1] findAlbum : Collection (MPDAlbum)
and you need to a intermediate MPDAlbum object:
user> (.findAlbum db (MPDAlbum. "Crisis"))
#<ArrayList []>