I am trying to write a couple of wrapper functions for the code here
it basically has the form (as given in the example page) of
String json = ...
VPackParser parser = new VPackParser.Builder().build();
VPackSlice slice = parser.fromJson(json);
I am aware that To import inner classes one uses $, but every combination of the following doesn't seem to work.
(ns the.pain.is.real
(:require [clojure.reflect :as r])
(:import
com.arangodb.velocypack.VPackBuilder ;; fine
com.arangodb.velocypack.VPackSlice ;; fine
com.arangodb.velocypack.VPackParser ;; fine
com.arangodb.velocypack.VPack ;; fine
com.arangodb.velocypack.VPackParser$Builder ;; nope
))
I just get a Unhandled java.lang.ClassNotFoundException.
I had worked with some similar code that I had got working using:
(ns winning
(:import com.arangodb.ArangoDB$Builder))
(.build (-> (new ArangoDB$Builder)
(.host "127.0.0.1" 8529)
(.user username)
(.password password)))
Any ideas?
looking in the jar file does show
com/arangodb/velocypack/VPackParser$Builder.class
Is it just trial and error?
Answering my own question.
It appears that two versions were downloaded when using lein deps. Even though only [com.arangodb/velocypack "1.0.0"] was in the project file, both 1.0.0 and 1.0.10 were in the .m2 dir. The class com/arangodb/velocypack/VPackParser$Builder.class is only found in version 1.0.10.
After changing the project file to [com.arangodb/velocypack "1.0.10"] the import works.
Related
I just started trying out clojure. I am doing my best to start vibing with the lisp syntax style. I am using vs-code on a mac, project is created with leiningen, calva is working (jack-in). Every time I try to import a library, for example
(ns asdf.core
(:gen-class)
(:require [clojure.string :refer [index-of]]))
and then adding
(index-of "ab" "ab")
somewhere under my main and press opt + enter I get a syntax error with the message
; Syntax error compiling at (src/asdf/core.clj:40:1).
; Unable to resolve symbol: index-of in this context
I already tried googling but only found that my name space might have to be changed to (ns asdf.core) again, but adding that in front of the index-of call doesn't help. Functions that I don't need to import/require like (+ 1 1) just work fine with the repl.(obviously the whole file should be in asdf.core ns, or am I wrong?)
I am trying to use https://github.com/ptaoussanis/timbre to log to a file rather than the console. Here is some documentation I've found on how to do that:
; The default setup is simple console logging. We with to turn off console logging and
; turn on file logging to our chosen filename.
(timbre/set-config! [:appenders :standard-out :enabled?] false)
(timbre/set-config! [:appenders :spit :enabled?] true)
(timbre/set-config! [:shared-appender-config :spit-filename] log-file-name)
(timbre/set-config! [:shared-appender-config :spit-filename] log-file-name)
This works for a previous version of sente, but not for version [com.taoensso/timbre "4.3.1"]. (For unrelated reasons I need to use the latest). The issue with the above code is that set-config! now takes one argument - a hash-map. And I can't find any documentation that would help me with translating the above 'two params' code to the new 'one param' code.
I know there's a very similar question out there. This question has actual code in it so is more specific. I raised an issue as well. The code above basically comes straight from here.
To log to a file rather than the console in timbre v4.0.0 (2015 June 10) you can do the following:
(ns app.core
(:require [taoensso.timbre :as timbre]
[taoensso.timbre.appenders.core :as appenders]))
;; Disable logging to the console in timbre v4.0.0:
(timbre/merge-config! {:appenders {:println {:enabled? false}}})
;; Create a "spit to file" appender in timbre v4.0.0:
(timbre/merge-config! {:appenders {:spit (appenders/spit-appender {:fname "log.txt"})}})
Note that in timbre v4.3.1 the following does not remove nor disable the println (console) appender:
(timbre/merge-config! {:appenders {:println nil}})
The related issue can be found here https://github.com/ptaoussanis/timbre/issues/163
Addition:
As Timbre allows to modify it's config map timbre/*config* simply by using
the standard clojure API, you may also use
(timbre/swap-config! assoc-in [:appenders :spit :enabled?] false)
(timbre/swap-config! assoc-in [:appenders :spit] (appenders/spit-appender {:fname "log.txt"}))
Based on this you can additionally define a simple helper:
(def set-log-config-param! (partial timbre/swap-config! assoc-in))
and then be consistent with the timbre v3.4.0 set-config! syntax you
have quoted in your question:
(set-log-config-param! [:appenders :println :enabled?] false)
(set-log-config-param! [:appenders :spit] (appenders/spit-appender {:fname "log.txt"}))
Imho this eases the config transition between timbre v3 and v4 and makes the path to
the params more readable then the equivalent
(timbre/merge-config! {:appenders {:println {:enabled? false}}})
(timbre/merge-config! {:appenders {:spit (appenders/spit-appender {:fname "log.txt"})}})
I got a quick response from the maintainer:
"Usage of the spit (file) appender is documented in the README at https://github.com/ptaoussanis/timbre#file-appender"
And here's the code to answer the question:
;; (:require [taoensso.timbre.appenders.core :as appenders]) ; Add to ns
(timbre/merge-config!
{:appenders {:println nil ; Remove println appender
:spit (appenders/spit-appender {:fname log-file-name})}})
Unfortunately even with the :println nil mapentry the same output will go to two places. So this answer is incorrect.
Let's say I create a new Leiningen project (lein new app example) and add some code in example/src/example/core.clj that makes use of :gen-class:
(ns example.core
(:gen-class :extends javafx.application.Application))
(defn -start [this stage]
(.show stage))
(defn -main [& args]
(javafx.application.Application/launch example.core args))
If I then create a JAR (lein uberjar) and run it, everything works fine. However, if I instead try to run my app directly (lein run), I get a ClassNotFoundException. In addition, if I open a REPL (lein repl), I first get the same error as before, but after running this code:
(compile 'example.core)
the error no longer appears in lein run or lein repl.
Could someone please explain to me what exactly is going on here, and how I can run my app directly without needing to manually compile my code from a REPL?
Edit: After fooling around a bit more, I found that the solution to this problem is to add
:aot [example.core]
to project.clj. (Thanks #Mars!) I'm still confused, though, because I had previously tried simply removing ^:skip-aot, which (according to the docs) should work:
This will be AOT compiled by default; to disable this, attach
^:skip-aot metadata to the namespace symbol.
But it doesn't. Why?
Another edit (if I should split any of this into a separate question, let me know and I'll do so): I've been playing with hyphens (lein new app my-example), and weird stuff has been happening. This doesn't work:
(ns my-example.core
(:gen-class :extends javafx.application.Application))
;; ...
(defn -main [& args]
(javafx.application.Application/launch my-example.core args))
But this does:
(ns my-example.core
(:gen-class
:name my-example.Core
:extends javafx.application.Application))
;; ...
(defn -main [& args]
(javafx.application.Application/launch my-example.Core args))
So my class name can either start with a lowercase letter (example.core) or contain a hyphen (my-example.Core), but not both? I really don't get it.
And finally, lein uberjar fails on that final example (with the explicit :name), because
Warning: The Main-Class specified does not exist within the jar. It may not be executable as expected. A gen-class directive may be missing in the namespace which contains the main method.
As far as I can tell, the only way to fix that is to split the Application subclass into a separate namespace. Is there another way?
Agreed with #Mars, the problem is that lein run does not AOT the example.core namespace. The default Leiningen template made the example.core non AOT:
(defproject example "0.1.0-SNAPSHOT"
...
:main ^:skip-aot example.core
...)
My best guess is that you could define your app using defrecord and use that as a class instead of the namespace.
JavaFX 8, Java 1.8.0_31, Windows 7 x64
I have a minimal JavaFX program in Clojure. The (ns...) clause is able to import the required Java packages fine except the classes in javafx.scene.control, such as Button and TextField, etc.
I have to put the import for these after initializing the toolkit. Why can't I import these classes before the toolkit is initialized? I'm not actually creating any objects yet... so I'm guessing JFX is somehow doing something in the background while these classes are imported, requiring the initialization first. Below is my complete lein project (minimized from the actual application where I saw this problem, and without all the nice macros that clean up the JFX syntax):
File project.clj:
(defproject jfx-so "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.6.0"]]
:main jfx-so.core)
File src/jfx_so/core.clj:
(ns jfx-so.core
(:import [javafx.scene Scene]
[javafx.scene.layout BorderPane]
[javafx.stage Stage]))
(defonce force-toolkit-init (javafx.embed.swing.JFXPanel.))
;; For some reason the following must be imported after initting the toolkit
(import [javafx.scene.control Button])
(defn -main [& args]
(javafx.application.Platform/runLater
#(doto (Stage.)
(.setScene (Scene. (BorderPane. (Button. "Hello"))))
(.show))))
Thanks! :)
I haven't had a problem with this. Perhaps it has to do with your defonce?
I do my imports first. But I do make sure to init the FX-envoronment before instanciating any FX-classes. So after your -main-method I would put:
(defn -main [& args]
;;body here
)
;; initialze the environement
(javafx.embed.swing.JFXPanel.)
;; ensure I can keep reloading and running without restarting JVM every time
(javafx.application.Platform/setImplicitExit false)
;; then
(-main)
Hope this helps.
I used to like to include all of clojure.contrib, and require all the libraries. This makes find-doc useful as a discovery tool.
Nowadays (clojure 1.4) clojure.contrib is split into many sub-libraries. And that rather spoils my scheme, and it also means that I am constantly having to restart the JVM every time I need a new library.
So I'm busy constructing a project.clj file with many lines:
[org.clojure/algo.generic "0.0.6"]
....
[org.clojure/data.xml "0.0.4"]
....
So that I can get leiningen to put every clojure contrib library on the classpath, whether I need them or not.
And I reckon that this is going to be a spectacular pain in the neck, what with the version numbers, and all.
And I wonder if anyone has a better way to do the same thing?
EDIT: Thinking about it, if there's a web page somewhere that has a list of library names and current versions, I can turn that into a project file fairly easily.
You could use pomegranate if you just want to run it in the REPL (which seems like it would be the only appropriate use case, right?). You can have it look up the latest versions using the Maven Central API. I think this is better than maintaining some sort of dependencies project, generated or otherwise.
(require '[cemerick.pomegranate :refer [add-dependencies]])
(add-dependencies
:coordinates '[[clj-http "0.5.8"]]
:repositories {"clojars" "http://clojars.org/repo"})
(require '[clj-http.client :as client])
;; contrib project names from https://github.com/clojure
(def contrib ["tools.nrepl" "tools.trace" "tools.namespace" "tools.macro"
"test.generative" "math.numeric-tower" "core.match" "core.logic"
"data.priority-map" "core.contracts" "tools.cli" "java.jmx"
"java.jdbc" "java.classpath" "data.xml" "data.json" "core.unify"
"core.incubator" "core.cache" "algo.monads" "data.generators"
"core.memoize" "math.combinatorics" "java.data" "tools.logging"
"data.zip" "data.csv" "algo.generic" "data.codec"
"data.finger-tree"])
(defn add-contrib-dependencies
"look up the latest version of every contrib project in maven central,
and add them as dependencies using pomegranate."
[project-names]
(add-dependencies
:coordinates
(map (juxt
(comp symbol (partial format "org.clojure/%s"))
(fn [proj]
(Thread/sleep 100)
(-> "http://search.maven.org/solrsearch/select?q=%s&rows=1&wt=json"
(format proj)
(client/get {:as :json})
:body :response :docs first :latestVersion)))
project-names)))
Now you can just invoke this function on the list of project names:
user=> (add-contrib-dependencies contrib)
{[org.clojure/data.zip "0.1.1"] nil,
[org.clojure/java.classpath "0.2.0"] nil,
[org.clojure/core.cache "0.6.2"] nil, ...}
UPDATE: as suggested earlier, I had made this answer into a library. It can be used either as nREPL middleware or invoked manually from a running REPL session. The code can be found at https://github.com/rplevy/contrib-repl, where usage instructions can also be found.
I feel your pain. It should be helpful http://dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go