Capture USB-microphone in clojure overtone - clojure

How I can use USB-mic in Overtone?
Here is an example to use regular 3.5mm microphone:
(ns insane-noises.vocoder)
(use 'overtone.live)
(def a (buffer 2048))
(def b (buffer 2048))
(demo 5
(let [input (sound-in 0); mic
src (white-noise) ; synth - try replacing this with other sound sources
formed (pv-mul (fft a input) (fft b src))
audio (ifft formed)]
(pan2 (* 0.1 audio))))
When I try in (sound-in 0) change 0 to 1, 2, 3... - nothing works.
My mic works good in all applications like skype etc.

I've just tried to reproduce it. It works only intermittently. I ran
(event-debug-on)
in the REPL, allowing me to see the OSC communication between Overtone and SuperCollider.
It fails in two different ways depending on whether I'm using overtone.core and connecting to an external server, or using overtone.live.
With overtone.live, I allocate the buffers just fine, but when I run the demo function, I get:
event: [:overtone :osc-msg-received] (:msg {:path "/done", :type-tag "s", :args ("/d_recv")})
event: "/done" (:path "/done" :args ("/d_recv"))
event: [:overtone :osc-msg-received] (:msg {:path "/synced", :type-tag "i", :args (18)})
event: "/synced" (:path "/synced" :args (18))
zombified - calling shutdown handler
event: [:overtone :osc-msg-received] (:msg {:path "/n_go", :type-tag "iiiii", :args (34 7 -1 -1 0)})
event: "/n_go" (:path "/n_go" :args (34 7 -1 -1 0))
event: [:overtone :node-created 34] ({:node #<synth-node[live]: beatboxchad-l394/audition-synth 34>})
... followed by a bunch of events related to Overtone cleaning up its default nodes and groups and such as part of shutting down. If you don't get the same output from your overtone.live, I'll know I have something to troubleshoot about my JACK settings or something.
Using overtone.core connected to an external server, it works intermittently.
When it works, I get the following events:
event: [:overtone :osc-msg-received] (:msg {:path "/d_removed", :type-tag "s", :args ("beatboxchad-l394/audition-synth"), :src-host "localhost.localdomain", :src-port 57110})
event: "/d_removed" (:path "/d_removed" :args ("beatboxchad-l394/audition-synth"))
event: [:overtone :osc-msg-received] (:msg {:path "/done", :type-tag "s", :args ("/d_recv"), :src-host "localhost.localdomain", :src-port 57110})
event: "/done" (:path "/done" :args ("/d_recv"))
event: [:overtone :osc-msg-received] (:msg {:path "/synced", :type-tag "i", :args (71), :src-host "localhost.localdomain", :src-port 57110})
event: "/synced" (:path "/synced" :args (71))
event: [:overtone :osc-msg-received] (:msg {:path "/n_go", :type-tag "iiiii", :args (114 7 -1 -1 0), :src-host "localhost.localdomain", :src-port 57110})
event: "/n_go" (:path "/n_go" :args (114 7 -1 -1 0))
event: [:overtone :node-created 114] ({:node #<synth-node[live]: beatboxchad-l394/audition-synth 114>})
event: [:overtone :osc-msg-received] (:msg {:path "/n_end", :type-tag "iiiii", :args (114 7 -1 -1 0), :src-host "localhost.localdomain", :src-port 57110})
event: "/n_end" (:path "/n_end" :args (114 7 -1 -1 0))
event: [:overtone :node-destroyed 114] ({:node #<synth-node[destroyed]: beatboxchad-l394/audition-synth 114>})
When it fails, I get these:
event: [:overtone :osc-msg-received] (:msg {:path "/d_removed", :type-tag "s", :args ("beatboxchad-l394/audition-synth"), :src-host "localhost.localdomain", :src-port 57110})
event: "/d_removed" (:path "/d_removed" :args ("beatboxchad-l394/audition-synth"))
event: [:overtone :osc-msg-received] (:msg {:path "/done", :type-tag "s", :args ("/d_recv"), :src-host "localhost.localdomain", :src-port 57110})
event: "/done" (:path "/done" :args ("/d_recv"))
event: [:overtone :osc-msg-received] (:msg {:path "/synced", :type-tag "i", :args (72), :src-host "localhost.localdomain", :src-port 57110})
event: "/synced" (:path "/synced" :args (72))
event: [:overtone :osc-msg-received] (:msg {:path "/fail", :type-tag "ss", :args ("/s_new" "duplicate node ID"), :src-host "localhost.localdomain", :src-port 57110})
event: "/fail" (:path "/fail" :args ("/s_new" "duplicate node ID"))
This looks like a malfunction in the OSC communication with the server -- somewhere the node ID isn't getting incremented correctly.
What do you get in terms of events when you try?

Related

Clojure nested json response

I am new to clojure and I am trying to make a simple API with 3 endpoints.
I am trying to implement an endpoint which will take each row of a query and put it to a json.
So I have an SQLite database. These are my entries for example:
{:timestamp 2020-09-11 14:29:30, :lat 36.0, :long 36.0, :user michav}
{:timestamp 2020-09-11 14:31:47, :lat 36.0, :long 36.0, :user michav}
So I want a json response like the below:
{:get
:status 200
:body {:timestamp "2020-09-11 14:29:30"
:lat 36.0
:long 36.0
:user "michav"}
{:timestamp "2020-09-11 14:31:47"
:lat 36.0
:long 36.0
:user "michav"}
}
}
Here is my code that I am trying to fix it in order to get the above result.
(def db
{:classname "org.sqlite.JDBC"
:subprotocol "sqlite"
:subname "db/database.db"
})
(defn getparameter [req pname] (get (:params req) pname))
(defn output
"execute query and return lazy sequence"
[]
(query db ["select * from traffic_users"]))
(defn print-result-set
"prints the result set in tabular form"
[result-set]
(doseq [row result-set]
(println row)))
(defn request-example [req]
(response {:get {:status 200
:body (-> (doseq [row output]
{:timestamp (getparameter row :timestamp) :lat (getparameter row :lat) :long (getparameter row :long) :user (getparameter row :user)} ))
}}))
(defroutes my_routes
(GET "/request" [] request-example)
(route/resources "/"))
(def app (-> #'my_routes wrap-cookies wrap-keyword-params wrap-params wrap-json-response))
The error I encounter is the following :
java.lang.IllegalArgumentException: Don't know how to create ISeq from: mybank.core$output
RT.java:557 clojure.lang.RT.seqFrom
RT.java:537 clojure.lang.RT.seq
core.clj:137 clojure.core/seq
core.clj:137 clojure.core/seq
core.clj:65 mybank.core/request-example[fn]
core.clj:65 mybank.core/request-example
core.clj:63 mybank.core/request-example
response.clj:47 compojure.response/eval1399[fn]
response.clj:7 compojure.response/eval1321[fn]
core.clj:158 compojure.core/wrap-response[fn]
core.clj:128 compojure.core/wrap-route-middleware[fn]
core.clj:137 compojure.core/wrap-route-info[fn]
core.clj:146 compojure.core/wrap-route-matches[fn]
core.clj:185 compojure.core/routing[fn]
core.clj:2701 clojure.core/some
core.clj:2692 clojure.core/some
core.clj:185 compojure.core/routing
core.clj:182 compojure.core/routing
RestFn.java:139 clojure.lang.RestFn.applyTo
core.clj:667 clojure.core/apply
core.clj:660 clojure.core/apply
core.clj:192 compojure.core/routes[fn]
Var.java:384 clojure.lang.Var.invoke
cookies.clj:171 ring.middleware.cookies/wrap-cookies[fn]
keyword_params.clj:32 ring.middleware.keyword-params/wrap-keyword-params[fn]
params.clj:57 ring.middleware.params/wrap-params[fn]
json.clj:42 ring.middleware.json/wrap-json-response[fn]
Var.java:384 clojure.lang.Var.invoke
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:27 ring.adapter.jetty/proxy-handler[fn]
(Unknown Source) ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$ff19274a.handle
HandlerWrapper.java:127 org.eclipse.jetty.server.handler.HandlerWrapper.handle
Server.java:500 org.eclipse.jetty.server.Server.handle
HttpChannel.java:386 org.eclipse.jetty.server.HttpChannel.lambda$handle$1
HttpChannel.java:562 org.eclipse.jetty.server.HttpChannel.dispatch
HttpChannel.java:378 org.eclipse.jetty.server.HttpChannel.handle
HttpConnection.java:270 org.eclipse.jetty.server.HttpConnection.onFillable
AbstractConnection.java:311 org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded
FillInterest.java:103 org.eclipse.jetty.io.FillInterest.fillable
ChannelEndPoint.java:117 org.eclipse.jetty.io.ChannelEndPoint$2.run
EatWhatYouKill.java:336 org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask
EatWhatYouKill.java:313 org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce
EatWhatYouKill.java:171 org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce
EatWhatYouKill.java:135 org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce
QueuedThreadPool.java:806 org.eclipse.jetty.util.thread.QueuedThreadPool.runJob
QueuedThreadPool.java:938 org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run
(Unknown Source) java.lang.Thread.run
Your mistake is on this line:
(doseq [row output] ...
The error message
Don't know how to create ISeq from: mybank.core$output
gives the clue. The variable output is the function, not a sequence like doseq expects. You meant to call the output function, so you need to use parentheses to create a function call like:
(doseq [row (output)] ...
Update
You need to include an external library to convert between EDN data and a JSON string. My favorite way is my own library Tupelo Clojure. Use it like this:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(let [data [{:timestamp "2020-09-11 14:29:30", :lat 36.0, :long 36.0, :user "michav"}
{:timestamp "2020-09-11 14:31:47", :lat 36.0, :long 36.0, :user "michav"}]]
(println (edn->json data)))
with result:
[{"timestamp":"2020-09-11 14:29:30","lat":36.0,"long":36.0,"user":"michav"},
{"timestamp":"2020-09-11 14:31:47","lat":36.0,"long":36.0,"user":"michav"}]
You will need a line like this in your project.clj:
[tupelo "20.08.27"]
Please also see this template project for an easy way to get started. Enjoy!

How do you set up middleware in Clojure using Reitit to enable coercion of body params?

I am trying to set a a Reitit router that performs coercion. I can get the response section working but I can't seem to get the body coercion to work properly. The following is the code I am using:
(ns example
(:require
[ring.middleware.json :refer [wrap-json-body wrap-json-response]]
[ring.middleware.reload :refer [wrap-reload]]
[ring.util.response :refer [response]]
[reitit.ring.coercion :as rrc]
[reitit.coercion.malli]
[reitit.ring :as ring]))
(def router
(ring/ring-handler
(ring/router
[["/healthz" {:get (fn [_] {:status 200 :body "healthy"})}]
["/api" {:coercion reitit.coercion.malli/coercion
:middleware [rrc/coerce-exceptions-middleware
rrc/coerce-request-middleware
rrc/coerce-response-middleware]}
["/messages" {:post {:summary "Add a new message"
:parameters {:body [:map [:name string?]]}
:responses {200 {:body [:map
[:message string?]]}}
:handler (fn [req]
{:status 200 :body {:message (:name (:body req))}})}}]]]
{:data {:middleware []}})
(ring/create-default-handler)))
(def app (-> #'router
(wrap-reload)
(wrap-json-response)
(wrap-json-body {:keywords? true :bigdecimals? true})))
The coercion is failing even when I send the correct body parameters with the following error:
{
"schema": "[:map {:closed true} [:name string?]]",
"errors": [
{
"path": [],
"in": [],
"schema": "[:map {:closed true} [:name string?]]",
"value": null,
"type": "malli.core/invalid-type",
"message": "invalid type"
}
],
"value": null,
"type": "reitit.coercion/request-coercion",
"coercion": "malli",
"in": [
"request",
"body-params"
],
"humanized": [
"invalid type"
]
}
This seems to be indicating that the coercion can't find any body parameters. I assume this has to do with the way I am setting up my middleware but I can't seem to fix this. How should I set the middleware up so the Reitit coercion works properly in this case?
I was able to get coercion to work by removing the wrap-json-response and wrap-json-body middleware and replacing it with the muuntaja middleware as follows:
(def router
(ring/ring-handler
(ring/router
[["/healthz" {:get (fn [_] {:status 200 :body "healthy"})}]
["/api" {:coercion reitit.coercion.malli/coercion
:middleware []}
["/messages" {:name ::message
:post {:summary "Add a new message"
:parameters {:body [:map [:name string?]]}
:responses {200 {:body [:map
[:message string?]]}}
:handler (fn [{:keys [parameters]}]
{:status 200 :body {:message (:name (:body parameters))}})}}]]]
{:data {:muuntaja m/instance
:middleware [params/wrap-params
muuntaja/format-middleware
rrc/coerce-exceptions-middleware
rrc/coerce-request-middleware
rrc/coerce-response-middleware]}})
(ring/create-default-handler)))

How to read Clojure's spec :macro-syntax-check errors

I copied the following joy.gui.DynaFrame definition from "Joy of Closure" Chapter 12.2.1
(ns joy.gui
(:gen-class
:name joy.gui.DynaFrame
:extends javax.swing.JFrame
:implements [clojure.lang.IMeta]
:prefix df-
:state state
:init init
:constructors {[String] [String]
[] [String]}
:methods [[display [java.awt.Container] void]
^{:static true} [version [] String]]
)
(:import (javax.swing JFrame JPanel JComponent)
(java.awt BorderLayout Container)))
Unfortunately, the syntax for :prefix has apparently changed since 2014, so the line 6 should read :prefix "df-".
Evaluating the incorrect code above I got the following error message:
2. Unhandled clojure.lang.Compiler$CompilerException
Error compiling src/dipping_feet/gui.clj at (1:1)
#:clojure.error{:phase :macro-syntax-check,
:line 1,
:column 1,
:source
1. Caused by clojure.lang.ExceptionInfo
Call to clojure.core/ns did not conform to spec.
#:clojure.spec.alpha{:problems
[{:path [],
:reason "Extra input",
:pred
(clojure.spec.alpha/cat
:docstring
(clojure.spec.alpha/? clojure.core/string?)
:attr-map
(clojure.spec.alpha/? clojure.core/map?)
:ns-clauses
:clojure.core.specs.alpha/ns-clauses),
:val
((:gen-class
:name
joy.gui.DynaFrame
:extends
javax.swing.JFrame
:implements
[clojure.lang.IMeta]
:prefix
df-
:state
state
:init
init
:constructors
{[String] [String], [] [String]}
:methods
[[display [java.awt.Container] void]
[version [] String]])
(:import
(javax.swing JFrame JPanel JComponent)
(java.awt BorderLayout Container))),
:via [:clojure.core.specs.alpha/ns-form],
:in [1]}],
:spec
#object[clojure.spec.alpha$regex_spec_impl$reify__2509 0x3b982314 "clojure.spec.alpha$regex_spec_impl$reify__2509#3b982314"],
:value
(joy.gui
(:gen-class
:name
joy.gui.DynaFrame
:extends
javax.swing.JFrame
:implements
[clojure.lang.IMeta]
:prefix
df-
:state
state
:init
init
:constructors
{[String] [String], [] [String]}
:methods
[[display [java.awt.Container] void]
[version [] String]])
(:import
(javax.swing JFrame JPanel JComponent)
(java.awt BorderLayout Container))),
:args
(joy.gui
(:gen-class
:name
joy.gui.DynaFrame
:extends
javax.swing.JFrame
:implements
[clojure.lang.IMeta]
:prefix
df-
:state
state
:init
init
:constructors
{[String] [String], [] [String]}
:methods
[[display [java.awt.Container] void]
[version [] String]])
(:import
(javax.swing JFrame JPanel JComponent)
(java.awt BorderLayout Container)))}
I omit the stack trace here.
My question is: is there a reference in the error message somewhere which would point me to the exact location of the error in the code? I had to basically guess which part of my definition is incorrect.
Yes, I agree, this is a confusing error message. This appears to be a bug in spec, so unfortunately I don't think there is anything you can do at this time to make the error any better.
https://clojure.atlassian.net/browse/CLJ-2013?oldIssueView=true

Clojure - use a core.async channel with Yada/Aleph

I am trying to use Clojure manifold library, and in order to understand it, I need wanted to convert a core.async channel into a manifold stream.
I would like to create the equivalent the following using a core.async channel :
(require '[manifold.stream :as s])
(s/periodically 100 #(str " ok "))
;; Here is what I tried, it fails with an error 500
(let [ch (chan)]
(go-loop []
(>! ch " ok ")
(<! (timeout 100))
(recur))
(s/->source ch))
I am trying to feed a core.async channel into yada. The first code sample, using manifold.stream/periodic works, not the others using core.async. I tried on yada 1.0.0 and 1.1.0-SNAPSHOT.
Using manifold.stream/periodic works :
(def get-stream
(yada (fn [ctx]
(-> (:response ctx)
(assoc :status 202)
(assoc :body (s/periodically 1000 #(str (System/currentTimeMillis) " ")))))
{:representations [{:media-type "application/json"
:charset "UTF-8"}
{:media-type "application/edn"
:charset "UTF-8"}]}))
Using manifold.stream/->source returns an error 500 :
(def get-stream
(yada (fn [ctx]
(-> (:response ctx)
(assoc :status 202)
;; Similar to this : https://github.com/juxt/yada/blob/94f3ee93de155a8513b27e0508608691ed556a55/dev/src/yada/dev/async.clj
(assoc :body (let [ch (chan)]
(go-loop []
(>! ch " ok ")
(<! (timeout 100))
(recur))
(s/->source ch)))))
{:representations [{:media-type "application/json"
:charset "UTF-8"}
{:media-type "application/edn"
:charset "UTF-8"}]}))
;; Error on the page :
;; 500: Unknown
;; Error on GET
;; #error {
;; :cause "No implementation of method: :to-body of protocol: #'yada.body/MessageBody found for class: manifold.stream.async.CoreAsyncSource"
;; :via
;; [{:type clojure.lang.ExceptionInfo
;; :message "Error on GET"
;; :data {:response #yada.response.Response{:representation {:media-type #yada.media-type[application/json;q=1.0], :charset #yada.charset.CharsetMap{:alias "UTF-8", :quality 1.0}}, :vary #{:media-type}}, :resource #function[backend.routes.examples.ts/fn--57734]}
;; :at [clojure.core$ex_info invoke "core.clj" 4593]}
;; {:type java.lang.IllegalArgumentException
;; :message "No implementation of method: :to-body of protocol: #'yada.body/MessageBody found for class: manifold.stream.async.CoreAsyncSource"
;; :at [clojure.core$_cache_protocol_fn invoke "core_deftype.clj" 554]}]
;; :trace
Third attempt, with a core.async channel (different error 500) :
(def get-stream
(yada (fn [ctx]
(-> (:response ctx)
(assoc :status 202)
(assoc :body (chan)))
{:representations [{:media-type "application/json"
:charset "UTF-8"}
{:media-type "application/edn"
:charset "UTF-8"}]}))
;; Error on the page :
;; 500: Unknown
;; Error on GET
;; #error {
;; :cause "No implementation of method: :to-body of protocol: #'yada.body/MessageBody found for class: clojure.core.async.impl.channels.ManyToManyChannel"
;; :via
;; [{:type clojure.lang.ExceptionInfo
;; :message "Error on GET"
;; :data {:response #yada.response.Response{:representation {:media-type #yada.media-type[application/json;q=1.0], :charset #yada.charset.CharsetMap{:alias "UTF-8", :quality 1.0}}, :vary #{:media-type}}, :resource #function[backend.routes.api.subscribe/subscribe$fn--64130]}
;; :at [clojure.core$ex_info invoke "core.clj" 4593]}
;; {:type java.lang.IllegalArgumentException
;; :message "No implementation of method: :to-body of protocol: #'yada.body/MessageBody found for class: clojure.core.async.impl.channels.ManyToManyChannel"
;; :at [clojure.core$_cache_protocol_fn invoke "core_deftype.clj" 554]}]
;; :trace
The key error is this:
"No implementation of method: :to-body of protocol:
#'yada.body/MessageBody
found for class: manifold.stream.async.CoreAsyncSource"
It reveals that the yada version you are using is trying to coerce a body type it doesn't understand. More recent versions of yada are more permissive about what you can send through to the web-server, and allow anything through that it doesn't know how to transform.

How to use http.kit server with drawbridge ring handler?

I have following server code:
(ns tweet-sentiment.server
(:require [clojure.java.io :as io]
[tweet-sentiment.dev :refer [is-dev? inject-devmode-html browser-repl start-figwheel start-less]]
[compojure.core :refer [GET POST defroutes]]
[compojure.route :refer [resources]]
[net.cgrand.enlive-html :refer [deftemplate]]
[net.cgrand.reload :refer [auto-reload]]
[ring.middleware.reload :as reload]
[ring.middleware.defaults :refer [wrap-defaults api-defaults]]
[tweet-sentiment.utils :refer [generate-response]]
[environ.core :refer [env]]
[org.httpkit.server :refer [run-server]]
[ring.middleware.edn :refer [wrap-edn-params]]
[tweet-sentiment.tweets :refer [tweets]]
[tweet-sentiment.dandelion :refer [dandelion-sentiment]]
[clojure.core.async :refer [>!! <!! put! take! pipe chan]]
[cemerick.drawbridge :as drawbridge]
[ring.middleware.basic-authentication :refer [wrap-basic-authentication]]
)
(:gen-class))
(defonce server (atom nil))
(deftemplate page (io/resource "index.html") []
[:body] (if is-dev? inject-devmode-html identity))
(defroutes routes
(resources "/")
(resources "/react" {:root "react"})
(GET "/*" req (page)))
(defn wrap-drawbridge [handler]
(fn [req]
(if (= "/repl" (:uri req))
(drawbridge/ring-handler req)
(handler req))))
(def http-handler
(if is-dev?
(-> #'routes
(wrap-defaults api-defaults)
reload/wrap-reload
wrap-edn-params
wrap-drawbridge)
(-> (wrap-defaults #'routes api-defaults)
wrap-edn-params
wrap-drawbridge)))
(defn run-web-server [& [port]]
(let [port (Integer. (or port (env :port) 10555))]
(println (format "Starting web server on port %d." port))
(reset! server (run-server http-handler {:port port :join? false}))))
(defn run-auto-reload [& [port]]
(auto-reload *ns*)
(start-figwheel)
(start-less))
(defn run [& [port]]
(when is-dev?
(run-auto-reload))
(run-web-server port))
(defn stop-server []
(when-not (nil? #server)
(#server :timeout 0)
(reset! server nil)))
(defn restart-server []
(stop-server)
(run-web-server))
(defn -main [& [port]]
(run port))
When I try to connect to drawbridge REPL as dev or production:
lein repl :connect http://localhost:10555/repl
I get following error:
ERROR - POST /repl
java.lang.IllegalArgumentException: No value supplied for key: {:remote-addr "127.0.0.1", :headers {"accept-encoding" "gzip, deflate", "connection" "close", "content-length" "48", "content-type" "application/x-www-form-urlencoded", "host" "localhost:10555", "user-agent" "Apache-HttpClient/4.3.3 (java 1.5)"}, :async-channel #<AsyncChannel /127.0.0.1:10555<->/127.0.0.1:60374>, :server-port 10555, :content-length 48, :websocket? false, :content-type "application/x-www-form-urlencoded", :character-encoding "utf8", :uri "/repl", :server-name "localhost", :query-string nil, :body #<BytesInputStream BytesInputStream[len=48]>, :scheme :http, :request-method :post}
at clojure.lang.PersistentHashMap.create(PersistentHashMap.java:77)
at cemerick.drawbridge$ring_handler.doInvoke(drawbridge.clj:49)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at tweet_sentiment.server$wrap_drawbridge$fn__21884.invoke(server.clj:36)
at org.httpkit.server.HttpHandler.run(RingHandler.java:91)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Problem is obviously in drawbridge/ring-handler function.
These are my dependencies:
[[org.clojure/clojure "1.6.0"]
[org.clojure/clojurescript "0.0-3058" :scope "provided"]
[ring "1.3.2"]
[ring/ring-defaults "0.1.4"]
[compojure "1.3.2"]
[enlive "1.1.6"]
[org.omcljs/om "0.8.8"]
[om-sync "0.1.1"]
[environ "1.0.0"]
[http-kit "2.1.19"]
[fogus/ring-edn "0.3.0"]
[prismatic/om-tools "0.3.11"]
[secretary "1.2.3"]
[sablono "0.3.4"]
[twitter-api "0.7.8"]
[racehub/om-bootstrap "0.5.3"]
[cheshire "5.2.0"]
[com.cemerick/drawbridge "0.0.7"]
[ring-basic-authentication "1.0.1"]]
Did anybody get working http.kit server with drawbrige? What am I missing?
I eventually figured it out, server file should look somewhat like this
(ns tweet-sentiment.server
(:require [clojure.java.io :as io]
[tweet-sentiment.dev :refer [is-dev? inject-devmode-html browser-repl start-figwheel start-less]]
[compojure.core :refer [GET POST defroutes]]
[compojure.route :refer [resources]]
[net.cgrand.enlive-html :refer [deftemplate]]
[net.cgrand.reload :refer [auto-reload]]
[ring.middleware.reload :as reload]
[ring.middleware.defaults :refer [wrap-defaults api-defaults]]
[tweet-sentiment.utils :refer [generate-response]]
[environ.core :refer [env]]
[org.httpkit.server :refer [run-server]]
[ring.middleware.edn :refer [wrap-edn-params]]
[clojure.core.async :refer [>!! <!! put! take! pipe chan]]
[cemerick.drawbridge :as drawbridge]
[ring.middleware.basic-authentication :refer [wrap-basic-authentication]]
[ring.middleware.params :as params]
[ring.middleware.keyword-params :as keyword-params]
[ring.middleware.nested-params :as nested-params]
[ring.middleware.session :as session]
)
(:gen-class))
(defonce server (atom nil))
(deftemplate page (io/resource "index.html") []
[:body] (if is-dev? inject-devmode-html identity))
(defroutes routes
(resources "/")
(resources "/react" {:root "react"})
(GET "/*" req (page)))
(defn authenticated? [name pass]
(= [name pass] [(System/getenv "AUTH_USER") (System/getenv "AUTH_PASS")]))
(def drawbridge-handler
(-> (drawbridge/ring-handler)
(keyword-params/wrap-keyword-params)
(nested-params/wrap-nested-params)
(params/wrap-params)
(session/wrap-session)))
(defn http-handler [handler]
(-> handler
(wrap-defaults api-defaults)
wrap-edn-params))
(defn wrap-http [handler]
(fn [req]
(let [handler (if (= "/repl" (:uri req))
(wrap-basic-authentication drawbridge-handler authenticated?)
(if is-dev?
(-> handler
http-handler
reload/wrap-reload)
(-> handler
http-handler)))]
(handler req))))
(defn run-web-server [& [port]]
(let [port (Integer. (or port (env :port) 10555))]
(println (format "Starting web server on port %d." port))
(reset! server
(run-server (wrap-http #'routes) {:port port :join? false})
)))
(defn run-auto-reload [& [port]]
(auto-reload *ns*)
(start-figwheel)
(start-less))
(defn run [& [port]]
(when is-dev?
(run-auto-reload))
(run-web-server port))
(defn stop-server []
(when-not (nil? #server)
(#server :timeout 0)
(reset! server nil)))
(defn restart-server []
(stop-server)
(run-web-server))
(defn -main [& [port]]
(run port))