ClojureScript: migrating from fetch to shoreleave - clojure

As webnoir got deprecated I've decided to migrate from fetch as described in docs, but for some reason shoreleave.remotes in not being compiled to Js and as a result I get
goog.require could not find: shoreleave.remotes.http_rpc
I've tried both remote-callback and remotes.macros. My ClojureScript namespace goes like this
(ns my.cljs.ns
(:require [shoreleave.remotes.http-rpc :as rpc])
(:require-macros [shoreleave.remotes.macros :as fm])
and backend
(ns my.backend
(:use my.views
(:require [compojure.route :as route]
[compojure.handler :as handler]
[cemerick.shoreleave.rpc :as rpc]))
)
(rpc/defremote get-data [last-changed]
[:foo]
)
(defroutes my-routes
(GET "/" [] (intro-view))
(route/files "/" {:root "resources/public"})
(route/not-found "<h1>Page not found</h1>"))
(def my-routing (-> #'my-routes
rpc/wrap-rpc
handler/site))
Any ideas how to get it working?
UPDATE: I found out that for some reason goog.require('shoreleave.remotes.http_rpc') goes before goog.provide('shoreleave.remotes.http_rpc')

it was a problem with incremental complition in lein (see bug CLJS-282), adding ':incremental false' in project.clj fixed my problem:
:cljsbuild {
:builds [{
:incremental false
:jar true
:source-path "src-cljs"
:compiler {
:output-to "resources/public/js/js.js"
:optimizations :whitespace
:pretty-print true}
}]}

I just solved this problem by adding two dependencies in project.clj.
[shoreleave "0.3.0"]
[shoreleave/shoreleave-remote "0.3.0"]

Related

java.lang.IllegalArgumentException: No implementation of method: :route-matches of protocol: #'clout.core/Route

I have two files of interest:
build.boot
(set-env!
:source-paths #{"src/clj" "src/cljs" "test/clj"}
:resource-paths #{"html" "target/main.js"}
:dependencies '[[adzerk/boot-cljs "0.0-3308-0"]
[adzerk/boot-cljs-repl "0.1.10-SNAPSHOT"]
[adzerk/boot-reload "0.3.1"]
[adzerk/boot-test "1.0.4"]
[cljsjs/hammer "2.0.4-4"]
[compojure "1.3.1"]
[com.datomic/datomic-pro "0.9.5186"]
[hiccup "1.0.5"]
[org.clojure/clojure "1.7.0-RC1"]
[org.clojure/clojurescript "0.0-3308"]
[org.clojure/core.async "0.1.346.0-17112a-alpha"]
[org.clojure/test.check "0.7.0"]
[org.omcljs/om "0.8.8"]
[pandeiro/boot-http "0.6.3-SNAPSHOT"]
[ring/ring-devel "1.4.0-RC1"]
[http-kit "2.1.18"]])
(require
'[adzerk.boot-cljs :refer [cljs]]
'[adzerk.boot-cljs-repl :refer [cljs-repl start-repl]]
'[adzerk.boot-reload :refer [reload]]
'[adzerk.boot-test :refer [test]]
'[pandeiro.boot-http :refer [serve]])
(task-options!
cljs {:source-map true
:optimizations :none
:pretty-print true})
(deftask build
"Build an uberjar of this project that can be run with java -jar"
[]
(comp
(cljs)
(aot :namespace '#{vidiot.server})
(pom :project 'vidiot
:version "0.1.0")
(uber)
(jar :main 'vidiot.server)))
and src/clj/vidiot/server.clj
(ns vidiot.server
(:gen-class)
(:require
[compojure.core :refer :all]
[compojure.route :as route]
[hiccup.core :refer :all]
[org.httpkit.server :refer :all]
[ring.middleware.reload :as reload]
[ring.util.response :as response]))
(defonce server (atom nil))
(defroutes all-routes
(GET "/" [] (response/redirect "index.html"))
(GET "/ws" [request]
(with-channel request channel
(on-close
channel
(fn [status]
(println "channel closed: " status)))
(on-receive
channel
(fn [data] ;; echo it back
(send! channel data)))))
(route/files "/" {:root "target"})
(route/not-found (response/response (html [:div#erro "Page Not Found"]))))
(defn -main [& args]
(run-server all-routes {:port 8080}))
Then I,
> boot build
> java -jar target/vidiot-0.1.0.jar
Followed by going to localhost:9090 in my browser, the terminal prints.
java.lang.IllegalArgumentException: No implementation of method: :route-matches of protocol: #'clout.core/Route found for class: clout.core.CompiledRoute
at clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:554)
at clout.core$eval5590$fn__5591$G__5581__5598.invoke(core.clj:39)
at compojure.core$if_route$fn__5887.invoke(core.clj:40)
at compojure.core$if_method$fn__5879.invoke(core.clj:27)
at compojure.core$routing$fn__5918.invoke(core.clj:127)
at clojure.core$some.invoke(core.clj:2568)
at compojure.core$routing.doInvoke(core.clj:127)
at clojure.lang.RestFn.applyTo(RestFn.java:139)
at clojure.core$apply.invoke(core.clj:630)
at compojure.core$routes$fn__5922.invoke(core.clj:132)
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)
I can fix this issue by downgrading :dependencies in build.boot to [compojure "1.1.6"].
So, my question is, why can't I use [compojure "1.3.4"] (the most recent version at this writing) when building my uberjar?
Placing aot task after uber fixes the issue.
(task-options! pom {:project 'my-project
:version "0.1.0"}
jar {:main 'my-project.core}
aot {:namespace '#{my-project.core}})
(deftask build []
(comp (pom)
(uber)
(aot)
(jar)))
I was able to fix this by adding an exclude for the clout folder. It looks like uberjar is unpacking some compiled clout files on top of those compiled from project source. Example from my project:
(comp (cljs :compiler-options {:output-to "js/main.js"})
(aot :namespace '#{zoondka-maps.server zoondka-maps.handler})
(pom :project (symbol (:name project))
:version (:version project))
(uber :exclude (conj pod/standard-jar-exclusions #".*\.html" #"clout/.*"))
(jar :file (str (:name project) ".jar")
:main 'zoondka-maps.server)))

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)))

Clojure require namespace: "Don't know how to create ISeq from: clojure.lang.Keyword"

I'm trying to split code in 2 files, each with it's own namespace. Following this tutorial.
But I get this error:
Exception in thread "main" java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Keyword
I think it's because the namespace being included is not recognised properly.
Main file:
(ns mytest2.handler
(:use compojure.core)
(:require [compojure.handler :as handler]
[compojure.route :as route]
[mytest2.views :as foo] ;<-- line causing error
[hiccup.core :refer (html)])
)
(defn layout [title & content]
(html
[:head [:title title]]
[:body content]))
(defn main-page []
(layout "My Blog"
[:h1 "My Blog"]
[:p "Welcome to my page"]))
(defroutes app-routes
(GET "/" [] (main-page))
(route/resources "/")
(route/not-found "Not Found"))
(def app
(handler/site app-routes))
; (println (seq (.getURLs (java.lang.ClassLoader/getSystemClassLoader))))
Second file:
(ns mytest2.views
:require [hiccup.core :refer (html)]
)
(defn layout [title & content]
(html
[:head [:title title]]
[:body content]))
(defn main-page []
(layout "My Blog"
[:h1 "My Blog"]
[:p "Welcome to my page"]))
(note I copied the functions from mytest2.views in mytest2.handler for testing. They're not supposed to be in mytest2.handler).
Paths of files:
/mytest2/src/mytest2/handler.clj
/mytest2/src/mytest2/views.clj
(where first mytest2 is the name of the project, and the second is part of the path- automatically created by lein).
As you see in the first file I printed the class path to verify that /mytest2/src/mytest2/ is included, and yes it is.
Received the same error from trying to use :refer :all in Clojurescript, which apparently is against the rules.
You missed some brackets in your original code
;; wrong
(ns mytest2.views
:require [hiccup.core :refer [html]])
There is just one pair of brackets missing. Do it as in your Main file:
;; Done right!
(ns mytest2.views
(:require [hiccup.core :refer [html]]))
I am not familar with Compojure so I do not know what you have to require. But you need to add the bracket around :require.

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.

Weird lein uberwar behavior

I'm executing lein uberwar for my test webapp and I'm getting the following weird error:
Exception in thread "main" java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.Symbol (servlet.clj:1)
The servlet.clj contains the following:
(ns test.servlet
(:use ring.util.servlet)
(:require test.routes :as routes)
(:gen-class :extends javax.servlet.http.HttpServlet))
(defservice routes/app-routes)
The test.routes file contains:
(ns test.routes
(:use compojure.core)
(:require [compojure.route :as route]
[compojure.handler :as handler]))
(defroutes app-routes
(GET "/" [] {:status 200
:headers {"Content-Type" "text/html"}
:body "<h1>Hello World</h1>"})
(route/files "/" {:root "static"})
(ANY "/:s" [s] (str "page-not-found" s)
;; For lein ring-server
;(def test-handler
; (handler/site app-routes))
The strange thing is that if I substitute the line
(:require test.routes :as routes)
With:
(:require test.routes)
And call
(defservice test.routes/app-routes)
In servlet.clj, the WAR compiles fine and it is working flawlessly in tomcat. Is there some bug in my code that I fail to see? Why do I need to call test.routes/... instead of just routes/...?
You need to put it inside a vector:
(:require [test.routes :as routes])