Missing *out* in Clojure with Lein and Ring - clojure

I am running Lein 2 and cider 0.7.0. I made a sample ring app that uses ring/run-jetty to start.
(ns nimbus-admin.handler
(:require [compojure.core :refer :all]
[compojure.handler :as handler]
[clojure.tools.nrepl.server :as nrepl-server]
[cider.nrepl :refer (cider-nrepl-handler)]
[ring.adapter.jetty :as ring]
[clojure.tools.trace :refer [trace]]
[ring.util.response :refer [resource-response response redirect content-type]]
[compojure.route :as route])
(:gen-class))
(defroutes app-routes
(GET "/blah" req "blah")
(route/resources "/")
(route/not-found (trace "not-found" "Not Found")))
(def app (handler/site app-routes))
(defn start-nrepl-server []
(nrepl-server/start-server :port 7888 :handler cider-nrepl-handler))
(defn start-jetty [ip port]
(ring/run-jetty app {:port port :ip ip}))
(defn -main
([] (-main 8080 "0.0.0.0"))
([port ip & args]
(let [port (Integer. port)]
(start-nrepl-server)
(start-jetty ip port))))
then connect to it with cider like:
cider-connect 127.0.0.1 7888
I can navigate to my site and eval forms in emacs and it will update what is running live in my nrepl session, so that is great.
I cannot see output, either with (print "test") (println "test") (trace "out" 1)
Finally, my project file:
(defproject nimbus-admin "0.1.0"
:description ""
:url ""
:min-lein-version "2.0.0"
:dependencies [[org.clojure/clojure "1.6.0"]
[com.climate/clj-newrelic "0.1.1"]
[com.ashafa/clutch "0.4.0-RC1"]
[ring "1.3.1"]
[clj-time "0.8.0"]
[midje "1.6.3"]
[org.clojure/tools.nrepl "0.2.6"]
[ring/ring-json "0.3.1"]
[org.clojure/tools.trace "0.7.8"]
[compojure "1.1.9"]
[org.clojure/data.json "0.2.5"]
[org.clojure/core.async "0.1.346.0-17112a-alpha"]
]
:plugins [[lein-environ "1.0.0"]
[cider/cider-nrepl "0.7.0"]]
:main nimbus-admin.handler)
I start the site with lein run
Edit
I CAN see output, ONLY when using (.println System/out msg)

Have you tried (.println System/out msg)? I had the same problem and this worked for me.

It's possible to just put print statements in your code manually.
If you want to print information about each request, you can add middleware.
The handler you pass to jetty is a function from Ring requests to Ring responses.
Ring request and responses are just maps, see the Ring spec for more which keys they should contain.
Middleware is just a function that takes a handler as its first argument and returns a handler.
Example of a middleware function to print basic info about requests and responses:
(defn log-middleware [handler]
(fn [request]
(let [response (handler request)]
(println "=>" (name (:request-method request)) ":" (:uri request))
(println "<=" (:status request))
response)))
This middleware should print to the cider repl buffer, but cider behaves strangely
sometimes and send output to *Messages* or the nrepl server buffer.
You use this middleware by applying it to your handlers:
(def application (log-middleware (handler/site routes)))
Headers could be printed this way to: just get the :headers field form the request map and print it.

The Prone library may help you out. It is has a ring middleware for better exception reporting that also has the ability for debugging. When debugging, you can inspect any local bindings as well as the Ring request.
Here is a video that demonstrates how it works

Use (flush) after your print expressions to force output.

Related

Clojure and Compojure: Response Map is nil

I'm using compojure for a basic web app, I have this code in core.clj:
(defroutes routes
(GET "/" [] (layout/application "Home" (contents/index)))
(route/resources "/"))
(def application (handler/site routes))
(defn -main []
(let [port (Integer/parseInt (or (System/getenv "PORT") "8090"))]
(jetty/run-jetty application {:port port :join? false})))
When I access the 0.0.0.0:8090 everything is loading ok, but I keep seeing this error:
java.lang.NullPointerException: Response map is nil
at ring.util.servlet$update_servlet_response.invokeStatic(servlet.clj:100)
at ring.util.servlet$update_servlet_response.invoke(servlet.clj:91)
at ring.util.servlet$update_servlet_response.invokeStatic(servlet.clj:95)
at ring.util.servlet$update_servlet_response.invoke(servlet.clj:91)
at ring.adapter.jetty$proxy_handler$fn__337.invoke(jetty.clj:27)
at ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$ff19274a.handle(Unknown Source)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.Server.handle(Server.java:503)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
at java.base/java.lang.Thread.run(Thread.java:844)
Any idea what's going on?
#Svante is almost certainly correct. An easy way to verify is to use the spyx function from the Tupelo library:
(ns demo.core
(:use tupelo.core))
(defroutes routes
(GET "/" [] (spyx (layout/application "Home" (contents/index))))
(route/resources "/"))
which will print something like:
(layout/application "Home" (contents/index))) => nil
when run. spyx ("spy explicit") prints the expression you give it, an arrow, and the expression value. spy, spyx, spy-pretty, etc also return the value printed (unlike println which always returns nil) so you can insert a spy printout anywhere without disrupting the processing chain. Thus, you don't need to write something like:
(defroutes routes
(GET "/" [] (let [tmp-1 (layout/application "Home" (contents/index))]
(println "layout/application result => " tmp-1)
tmp-1)))
(route/resources "/"))
in order to get a debug message printed. In order to spy & friends, add this to the :dependencies in your project.clj:
[tupelo "0.9.138"]
Update
Hmmmm.... Not sure what could be the problem. I made a simple demo app from lein new compojure demo-compojure with the following:
(ns demo-compojure.handler
(:use tupelo.core)
(:require [compojure.core :refer :all]
[compojure.route :as route]
[ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
(defn index []
(spy :index--result "Hello World"))
(defroutes app-routes
(GET "/" [] (spyx (index)))
(route/not-found "Not Found"))
(def app
(wrap-defaults app-routes site-defaults))
and results:
~/expr/demo-compojure > lein ring server
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Started server on port 3000
:index--result => "Hello World"
(index) => "Hello World"
So that is working. Also, int? is a basic Clojure function, so that is puzzling. Perhaps make a clean demo project like the above and take it from there?

How to run http-kit using boot?

I am not able to get any response from the http-kit server when running using boot. It works with jetty. When I run the boot run the it exits after sometime. So I added (boot (wait)) which doesn't terminate, but the server seems to be not running.
; core.clj
(ns server.core
(:use [compojure.route :only [files not-found]]
[compojure.handler :only [site]]
[compojure.core :only [defroutes GET POST DELETE ANY context]]
org.httpkit.server))
(defn hello []
"Hello from httpkit")
(defroutes api-routes
(GET "/" [] (hello)))
(defn -main []
(run-server api-routes {:port 8080}))
The boot.clj file:
;boot.clj
(set-env!
:source-paths #{"src"}
:dependencies '[[org.clojure/clojure "1.8.0"]
[ring "1.5.0"]
[compojure "1.5.1"]
[http-kit "2.2.0"]])
(require '[server.core :as server])
(deftask run []
(with-pre-wrap fileset (server/-main) fileset)
(boot (wait)))
You can use boot-http and something like the following:
(boot (serve :handler 'server/-main :reload true) (wait))

How to a json-rpc call from Clojure?

I've got a local server running on port 8545 which listen to JSON-RPC requests. I can call it using curl like this:
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0xf54c19d9ef3873bfd1f7a622d02d86249a328f06", "latest"],"id":1}' http://localhost:8545
What would be the equivalent call from Clojure? Do I need to add some external libraries to the project.clj?
I think you should try http-kit.
Also you will need some library for json (data.json or cheshire)
So add to your project.clj following dependencies:
[http-kit "2.1.18"]
[org.clojure/data.json "0.2.6"]
And try this
(ns your-ns
(:require [org.httpkit.client :as http]
[clojure.data.json :as json]))
(let [url "http://localhost:8545"
body (json/write-str
{:jsonrpc "2.0"
:method "eth_getBalance"
:params ["0xf54c19d9ef3873bfd1f7a622d02d86249a328f06" "latest"]
:id 1})
options {:body body}
result #(http/post url options)]
(prn result))
I had a similar use case so I created a small Clojure library for making JSON-RPC calls. With this, you can do,
(ns example.core
(:require [json-rpc.core :as rpc]))
(with-open [channel (rpc/open "http://localhost:8545")]
(rpc/send! channel "eth_blockNumber" ["latest"]))
;; => {:result "0x14eca", :id "6fd9a7a8-c774-4b76-a61e-6802ae64e212"}
, and the boilerplate will be handled for you.

Getting started with liberator

I am new to clojure and liberator.
I am trying to get started with liberator but I am stuck on the following error.
Here is my code that starts the webserver and defines the routes:
(ns game-of-life.core
(:require
[ring.util.response :as resp]
[compojure.route :as route]
[ring.adapter.jetty :as jetty])
(:use
[ring.middleware.multipart-params :only [wrap-multipart-params]]
[ring.util.response :only [header]]
[compojure.core :only [context ANY routes defroutes]]
[compojure.handler :only [api]]))
(defn assemble-routes []
(->
(routes
(ANY "/" [] (resp/redirect "/index.html"))
(route/resources "/"))))
(def handler
(-> (assemble-routes))
(defn start [options]
(jetty/run-jetty #'handler (assoc options :join? false)))
(defn -main
([port]
(start {:port (Integer/parseInt port)}))
([]
(-main "3000")))
When I run lein ring server, I get a java.lang.NullPointerException with the following stacktrace:
reload.clj:18 ring.middleware.reload/wrap-reload[fn]
stacktrace.clj:17 ring.middleware.stacktrace/wrap-stacktrace-log[fn]
stacktrace.clj:80 ring.middleware.stacktrace/wrap-stacktrace-web[fn]
jetty.clj:18 ring.adapter.jetty/proxy-handler[fn] (Unknown
Source) ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$0.handle
HandlerWrapper.java:116 org.eclipse.jetty.server.handler.HandlerWrapper.handle
Server.java:363 org.eclipse.jetty.server.Server.handle
AbstractHttpConnection.java:483 org.eclipse.jetty.server.AbstractHttpConnection.handleRequest
AbstractHttpConnection.java:920 org.eclipse.jetty.server.AbstractHttpConnection.headerComplete
AbstractHttpConnection.java:982 org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete
HttpParser.java:635 org.eclipse.jetty.http.HttpParser.parseNext
HttpParser.java:235 org.eclipse.jetty.http.HttpParser.parseAvailable
AsyncHttpConnection.java:82 org.eclipse.jetty.server.AsyncHttpConnection.handle
SelectChannelEndPoint.java:628 org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle
SelectChannelEndPoint.java:52 org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run
QueuedThreadPool.java:608 org.eclipse.jetty.util.thread.QueuedThreadPool.runJob
QueuedThreadPool.java:543 org.eclipse.jetty.util.thread.QueuedThreadPool$3.run
Thread.java:744 java.lang.Thread.run
I think it will work better if your handler function get the request argument.
Can you try changing the dependencies like this? These versions and the following config totally works for me: (including reloading)
(defproject ..........
:dependencies [[org.clojure/clojure "1.5.1"]
[liberator "0.11.0"]
[ring/ring-core "1.1.8"]
[ring/ring-jetty-adapter "1.1.8"]
[compojure "1.1.3"]]
:main game-of-life.core
:min-lein-version "2.0.0"
:plugins [[lein-ring "0.8.10"]]
:ring {:handler game-of-life.core/handler})
Plus the handler should be
(def handler
(-> (assemble-routes)))

Compojure app not playing well with with-redefs

I'm writing a Compojure application and am using clj-webdriver to graphically test it. I'm trying to use with-redefs to mock out the function that pulls out data from persistence to just return canned values, but it's ignoring my function overwrite. I know with-redefs works in terms of vars, but it's still not working:
project.clj relevant pieces:
(defproject run-hub "0.1.0-SNAPSHOT"
:main run-hub.handler/start-server)
handler.clj:
(ns run-hub.handler
(:require [compojure.core :refer :all]
[compojure.handler :as handler]
[compojure.route :as route]
[ring.adapter.jetty :refer :all]
[run-hub.controllers.log-controller :as log-controller]))
(defroutes app-routes
(GET "/MikeDrogalis/log" [] (log-controller/mikes-log))
(route/resources "/")
(route/not-found "Not Found"))
(def app (handler/site #'app-routes))
log-controller.clj:
(ns run-hub.controllers.log-controller
(:require [run-hub.views.log :as views]
[run-hub.persistence :as persistence]))
(defn mikes-log []
(views/mikes-log (persistence/mikes-log)))
persistence.clj
(ns run-hub.persistence
(require [clj-time.core :as time]
[run-hub.models.log :as log]))
(defn mikes-log [] [])
And finally, my graphical test - which tries to override mikes-log and fails:
(fact
"It has the first date of training as August 19, 2012"
(with-redefs [persistence/mikes-log (fn [] (one-week-snippet))]
(to (local "/MikeDrogalis/log"))
(.contains (text "#training-log") "August 19, 2012"))
=> true)
Where one-week-snippet is a function that returns some sample data.
(defn start-server []
(run-jetty (var app) {:port 3000 :join? false}))
I am able to use with-redefs in a clj-webdriver test doing the following:
(defn with-server
[f]
(let [server (run-jetty #'APP {:port 0 :join? false})
port (-> server .getConnectors first .getLocalPort)]
(binding [test-port port]
(try
(println "Started jetty on port " test-port)
(f)
(finally
(.stop server))))))
(use-fixtures :once with-server)
Then the whole bunch of tests gets its own jetty and this seems to run in
such a manner that with-redefs works.