How to run a clojure program in repl - clojure

(ns onyx.core
(:require [onyx.api]
[onyx.plugin.datomic]
(:import [com.mchange.v2.c3p0 ComboPooledDataSource]))
(def onyx-id (java.util.UUID/randomUUID))
I have a clojure project as above. I want to run the file in repl. How do I do it terminal?
lein repl
user=> (require..?)
what should be used there to get the onyx-id.

In your REPL, you should be able to
Require that namespace
(require '[onyx.core])
=> nil
Evaluate the var
onyx.core/onyx-id
=> #uuid "f1d49b2a-dfaa-4ea5-99a5-4af7ef0ce9b7"

Related

Using cprop env information inside swagger setup in a luminus project

I am using swagger to provide an API for a db access program. During development I normally have 2 versions running, the dev version and the prod version that I automatically start on login. I want to have a different title visible on the swagger front page so I don't accidentally trash my live database. So far I have been hand editing the title field in the swagger setup, but this is error prone, I often forget to change it before I run lein uberjar to build the prod version.
The env setup seems like an ideal way to do this. The luminus lein template already uses an env map that is built from dev and prod config files which works fine, allowing me to automatically specify different ports for the 2 builds. I added an entry to these that gives me a title that is different in prod and dev versions. I can see it from the repl, but including it in the swagger specification just gives null.
This is the :swagger definition from the start of my photo-api.routes.services.clj file:
(ns photo-api.routes.services
(:require [cheshire.core :as json]
[compojure.api.sweet :refer :all]
[image-lib.images :as ilim]
[image-lib.preferences :as ilpf]
[image-lib.projects :as ilpr]
[image-lib.write :as ilwr]
[photo-api.db.core :as db]
[photo-api.config :refer [env]]
[photo-api.routes.helpers.build :as build]
[photo-api.routes.helpers.keywords :as keywords]
[photo-api.routes.helpers.open :as open]
[photo-api.routes.helpers.photos :as photos]
[photo-api.routes.helpers.projects :as projects]
[ring.util.codec :refer [url-decode]]
[ring.util.http-response :refer [ok]]
[schema.core :as s]
[clojure.string :as str]))
(defapi service-routes
{:swagger {:ui "/swagger-ui"
:spec "/swagger.json"
:data
{:info
{:version "1.0.1"
;; Switch to correct title before lein uberjar
;; TODO Automate this so swagger page always shows dev or prod version
;;:title "Photo API"
:title (:title env)
:description "Access a mongo database containing details of photos"}}}}
The commented out :title specification works fine, but the (:title env) call doesn't although it is the exact same call I can successfully use from the repl. I believe the env map is built as part of photo-api.config and from the startup messages when I start the server it looks like this is being successfully started before the http-server:
{:started
["#'photo-api.config/env"
"#'photo-api.db.core/db*"
"#'photo-api.db.core/db"
"#'photo-api.handler/init-app"
"#'photo-api.handler/app"
"#'photo-api.core/http-server"]}
user>
This is photo-api.config, unchanged from the luminus default:
(ns photo-api.config
(:require [cprop.core :refer [load-config]]
[cprop.source :as source]
[mount.core :refer [args defstate]]))
(defstate env :start (load-config
:merge
[(args)
(source/from-system-props)
(source/from-env)]))
and the dev config.edn file:
{:title "**** Photos Development API ****"
:dev true
:port 31999
;; when :nrepl-port is set the application starts the nREPL server on load
:nrepl-port 57251}
Am I missing something obvious here? Is there another step necessary to make the env map visible to the swagger setup?
EDIT:
Changing the call from (:title env) to (env :title) causes cider-jack-in to fail with a long error message/stack trace that includes:
Caused by: java.lang.ClassCastException: mount.core.DerefableState cannot be cast to clojure.lang.IFn
Changing it again to (#env :title) then gives a similarly long error message/stack trace that contains:
Caused by: java.lang.ClassCastException: mount.core.NotStartedState cannot be cast to clojure.lang.IFn, compiling:(services.clj:29:23)
So it looks like env is not being started till after the call to it from the swagger setup. I still have no idea why as the when cider-jack-in did work it clearly showed the config.env state starting before the http-server. (see above)
It looks like (defstate env) is an atom that needs to be derefed. Mount's README points to the tests to for some examples .
You might try (:title #env) in service-routes
(defapi service-routes
{:swagger {:ui "/swagger-ui"
:spec "/swagger.json"
:data
{:info
{:version "1.0.1"
;; Switch to correct title before lein uberjar
;; TODO Automate this so swagger page always shows dev or prod version
;;:title "Photo API"
:title (:title #env) ;;;--------> UPDATED
:description "Access a mongo database containing details of photos"}}}}
EDIT --
Not an atom. See this issue for the same deref error, which, presumably means that no deref is needed.

Fastest way to try out a new library in a REPL using Leinengen with Clojure

New clojure developer trying to experiment with the HTTP kit clojure library in a REPL.
I created a new project in leinengen, lein new app kit-expt.
Then I modified the :dependencies block in project.clj to include [http-kit "2.2.0"].
Then I run lein deps, then lein repl.
In the REPL I try to run (:require [org.httpkit.client :as http]).
However, when I run this I get the error
CompilerException java.lang.ClassNotFoundException: org.httpkit.client, compiling:(/private/var/folders/cs/b0kcg6fx0335crbvn6xtgq7xl5c29j/T/form-init7575648818353088270.clj:1:1)
What am I doing wrong?
The :require form you're using is invalid, a keyword only for use in an ns (namespace) form. Try removing the : and just use (require ..., which is commonly used in a REPL. See more require examples here.
The HTTP Client docs you refer to assume you're in a source file using ns.
There appears to be something wrong in your environment. If I run it (Ubuntu 16.04) it works great:
(require '[org.httpkit.client :as http])
(pr-str (clojure.core/deref (http/get "http://google.com"))))
=> "{:opts {:method :get, :url \"http://www.google.com/\", :query-params nil, :form-params nil, :trace-re".....
Update
As Micah pointed out, in the repl you need the above form of require. Notice that it doesn't have the leading colon, and it does have a single-quote before the left square bracket. It must also be inside parentheses instead of square brackets.
In the ns form (which I prefer), everything has the opposite convention:
(ns tst.clj.core
(:use clj.core clojure.test tupelo.test)
(:require
[tupelo.core :as t]
[org.httpkit.client :as http] ))

lein test throws NPE for function using "resolve"; works in REPL

lein test throws a NullPointerException when testing a function that uses (resolve (symbol "a-fn")) to return function a-fn. The test runs fine from the REPL.
I have not been able to find a way to resolve a-fn in the testing suite for leiningen, if that is indeed the issue.
I created a Leiningen project called my-resolve by lein new my-resolve and added two functions and tests for them:
src/my_resolve/core.clj:
(ns my-resolve.core)
(defn a-fn [] "From a-fn")
(defn my-resolve [] (resolve (symbol "a-fn")))
test/my_resolve/core_test.clj:
(ns my-resolve.core-test
(:require [clojure.test :refer :all]
[my-resolve.core :refer :all]))
;; Passes
(deftest a-fn-test
(testing "a-fn"
(is (= (a-fn)
"From a-fn"))))
;; my-resolve-test behaves correctly in the REPL (the test passes,
;; returns nil) but throws a NullPointerException when called from
;; lein test.
(deftest my-resolve-test
(testing "my-resolve"
(is (= ((my-resolve))
"From a-fn"))))
Thank you.
resolve delegates to ns-resolve using the dynamically bound *ns*, which at the point of the call in my-resolve.core/my-resolve will be different depending on what namespace it is being called from:
user=> (doc resolve)
-------------------------
clojure.core/resolve
([sym] [env sym])
same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)
I assume that in the REPL you are calling my-resolve when in the my-resolve.core ns. When lein test executes the test in my-resolve.core-test, *ns* is dynamically bound to (the-ns 'user) and that ns (most likely) does not contain a binding to my-resolve.

Clojure namespace not accessible

I'm trying to load two namespaces from the library "spurious-aws-sdk-helper" (which by the way I've installed locally - this is me testing it before deploying to Clojars). And I'm loading the namespaces from inside an if statement.
Once the namespaces are loaded I call a function which is provided by one of the loaded namespaces.
The problem is that when executing the code via lein ring server I get a Java exception informing me that the namespace I'm trying to access isn't available.
But if I run lein repl and then (use 'spurious-clojure-example.routes.home) the relevant top level namespace; then (require '[spurious-aws-sdk-helper.core :as core]) the namespace - much like in the code I'll linked to in a moment demonstrates - then the namespace WILL be available and subsequently the call to the function won't error?
I'm not sure if it's one of those errors which are misleading and in fact it's not the namespace I'm trying to require that's the problem, but something inside of it that's the issue? But if that was true then why would it work when called manually by myself within lein repl?
The code I'm referring to is: https://github.com/Integralist/spurious-clojure-example/blob/baseline/src/spurious_clojure_example/routes/home.clj#L9-L10
(ns spurious-clojure-example.routes.home
(:use [amazonica.aws.s3])
(:require [compojure.core :refer :all]
[environ.core :refer [env]]
[spurious-clojure-example.views.layout :as layout]))
(if (env :debug)
(do
(require '[spurious-aws-sdk-helper.core :as core])
(require '[spurious-aws-sdk-helper.utils :refer [endpoint cred]])
(core/configure {:s3 "test-bucket4"
:sqs "test-queue4"
:ddb (slurp "./resources/config/schema.yaml")})))
(def bucket-path "news-archive/dev/election2014-council_title")
(def content
(apply str (line-seq
(clojure.java.io/reader
(:object-content
(get-object (cred (endpoint :spurious-s3)) :bucket-name "shared" :key bucket-path))))))
(defn home []
(layout/common [:h1 content]))
(defroutes home-routes
(GET "/" [] (home)))
It's the (core/configure ...) call that triggers a Java exception saying "core" namespace isn't available. But running the following code from lein repl works fine...
(use 'spurious-clojure-example.routes.home)
(require '[spurious-aws-sdk-helper.core :as core])
(core/configure ...rest of code...)
UPDATE 1:
Just to clarify I've updated the code as follows...
(when (env :debug)
(require '[spurious-aws-sdk-helper.core :as core])
(require '[spurious-aws-sdk-helper.utils :refer [endpoint cred]])
(core/configure
{:s3 "test-bucket7"
:sqs "test-queue9"
:ddb (slurp "./resources/config/schema.yaml")}))
...and when running it within the REPL it works fine.
The problem is when running it via lein ring server.
I've started reading about (ns-resolve) here: http://technomancy.us/143
But the solution it suggests: (ns-resolve 'core 'configure) didn't work; it just threw an Unable to resolve symbol: core in this context error.
I created a app with lein new compojure-app and when :debug value is truthy, require clojure.string :as str and then also printing something to shell.
The code below works via lein ring server. I tested it with :debug values true and false. I see in your example, you use environ so, I put {:debug true} or {:debug false} in .lein-env.
(ns integralist.handler
(:require [compojure.core :refer [defroutes routes]]
[ring.middleware.resource :refer [wrap-resource]]
[ring.middleware.file-info :refer [wrap-file-info]]
[hiccup.middleware :refer [wrap-base-url]]
[compojure.handler :as handler]
[compojure.route :as route]
[integralist.routes.home :refer [home-routes]]
[environ.core :refer [env]]))
(when (env :debug)
(require '[clojure.string :as str]))
(when (env :debug)
(defn it-works! []
(println "It works!:" (str/split "Clojure is Awesome" #" "))))
(defn init []
(println "integralist is starting")
(when (env :debug)
(it-works!)))
(defn destroy []
(println "integralist is shutting down"))
(defroutes app-routes
(route/resources "/")
(route/not-found "Not Found"))
(def app
(-> (routes home-routes app-routes)
(handler/site)
(wrap-base-url)))
Tried it with:
(when true ; also tried with false
(require '[clojure.string :as str])
(str/split "Clojure is awesome!" #" "))
=> No such namespace: str
I'm a tiny bit surprised as well since if and when should only evaluate the body of their expressions for the appropriate branch and not touch the other expressions. I did not expect a namespace error on false.
More surprising is I did not expect a namespace error on true as well. I'd guess it's some java compilation thing trying to resolve the namespace even before code evaluation. I don't know the specifics of why.
As for what you should do, this code is funky and I've never thought of or seen anyone doing anything similar. Unless there is some specific reason for doing this, the solution is simple: shove your requires to the very top in ns. There's no need to change anything else.

Why does read-line not return after hitting ENTER (seems like a hang) using lein run, but works with lein repl?

The problem at hand is that when I run my program with lein run it gets to the (read-line) part and I can't get out of it, meaning: read-line never returns.
Here is the relevant code:
(def command (atom ""))
(defn print-prompt []
(print "prompt> ")
(flush)
)
(defn ask-for-input []
(print-prompt)
(let [x (str (read-line))]
(println (str "User input: " x))
(reset! command x)
)
)
I never see the "User input: " string on screen.
The strange part is, if I run lein repl and call (ask-for-input) then it works correctly :S
Try lein trampoline run, it works.
The following is from leiningen FAQ:
Q: I don't have access to stdin inside my project.
A: This is a limitation of the JVM's process-handling methods; none of them expose stdin correctly. This means that functions like read-line will not work as expected in most contexts, though the repl task necessarily includes a workaround. You can also use the trampoline task to launch your project's JVM after Leiningen's has exited rather than launching it as a subprocess.
I tried your source code, but omitted the flush. It worked without a problem. What version of Clojure are you using? I tried the following code with Clojure 1.3.
(def command (atom 0))
(defn print-prompt []
(print "prompt> ")
)
(defn ask-for-input
[]
(print-prompt)
(let [x (str (read-line))]
(println (str "User input: " x))
(reset! command x)
))
Edit:
I altered one of your functions that I copied and tested with, and it works now with standalone and lein run. You had (flush) in your original example.
(defn print-prompt []
(print "prompt> ")
(flush)
)
From what I can garner, println causes a flush, print doesn't, and you need a flush after print.
I am adding this information in case it might be of help. I have a Clojure project called repl-test. Here is my repl-test project's core.clj file header. Your source, already posted, is in this file with some other functions, not related to your post.
(ns repl-test.core
(:gen-class)
(:use clojure.contrib.command-line)
(:require [clojure.contrib.string :as cstr])
(:require [clojure.contrib.trace :as ctr])
(:require [clojure.string :as sstr])
(:use clojure-csv.core))
And here is the project.clj file:
(defproject repl-test "0.0.1-SNAPSHOT"
:description "TODO: add summary of your project"
:dependencies [[org.clojure/clojure "1.3.0"]
[org.clojure/clojure-contrib "1.2.0"]
[clojure-csv/clojure-csv "1.2.4"]
[org.clojure/tools.cli "0.1.0"]
[clj-http "0.1.3"]]
:aot [repl-test.core]
:main repl-test.core)