我正在使用「Web Development with Clojure」一書來製作教程留言簿應用程序並遇到了麻煩。看起來,自本書發佈以來,一些圖書館及其功能已經更新,導致我對網絡開發的介紹略有顛簸。我可以通過更新依賴關係來解決大部分問題,或者在不能時使用舊版本的庫,但是這種策略已經達到了極限,並且遇到了一個棘手的問題。我得到這個堆棧跟蹤,當我嘗試到本地主機服務器上運行我的應用程序:「使用Clojure進行Web開發」:沒有這樣的變量:db/get-user
Exception in thread "main" java.lang.RuntimeException: No such var: db/get-user, compiling:(guestbook/routes/auth.clj:38:14)
at clojure.lang.Compiler.analyze(Compiler.java:6380)
at clojure.lang.Compiler.analyze(Compiler.java:6322)
at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3573)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6562)
at clojure.lang.Compiler.analyze(Compiler.java:6361)
at clojure.lang.Compiler.access$100(Compiler.java:37)
at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:5973)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6560)
at clojure.lang.Compiler.analyze(Compiler.java:6361)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6548)
at clojure.lang.Compiler.analyze(Compiler.java:6361)
at clojure.lang.Compiler.analyze(Compiler.java:6322)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5708)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5139)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3751)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6558)
at clojure.lang.Compiler.analyze(Compiler.java:6361)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6548)
at clojure.lang.Compiler.analyze(Compiler.java:6361)
at clojure.lang.Compiler.access$100(Compiler.java:37)
at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:529)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6560)
at clojure.lang.Compiler.analyze(Compiler.java:6361)
at clojure.lang.Compiler.analyze(Compiler.java:6322)
at clojure.lang.Compiler.compile1(Compiler.java:7148)
at clojure.lang.Compiler.compile(Compiler.java:7219)
at clojure.lang.RT.compile(RT.java:398)
at clojure.lang.RT.load(RT.java:438)
at clojure.lang.RT.load(RT.java:411)
at clojure.core$load$fn__5018.invoke(core.clj:5530)
at clojure.core$load.doInvoke(core.clj:5529)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5336)
at clojure.core$load_lib$fn__4967.invoke(core.clj:5375)
at clojure.core$load_lib.doInvoke(core.clj:5374)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$load_libs.doInvoke(core.clj:5413)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$require.doInvoke(core.clj:5496)
at clojure.lang.RestFn.invoke(RestFn.java:457)
at guestbook.handler$loading__4910__auto__.invoke(handler.clj:1)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.AFn.applyTo(AFn.java:151)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3458)
at clojure.lang.Compiler.compile1(Compiler.java:7153)
at clojure.lang.Compiler.compile1(Compiler.java:7143)
at clojure.lang.Compiler.compile(Compiler.java:7219)
at clojure.lang.RT.compile(RT.java:398)
at clojure.lang.RT.load(RT.java:438)
at clojure.lang.RT.load(RT.java:411)
at clojure.core$load$fn__5018.invoke(core.clj:5530)
at clojure.core$load.doInvoke(core.clj:5529)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5336)
at clojure.core$compile$fn__5023.invoke(core.clj:5541)
at clojure.core$compile.invoke(core.clj:5540)
at user$eval19.invoke(form-init6949279956252999274.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6619)
at clojure.lang.Compiler.eval(Compiler.java:6609)
at clojure.lang.Compiler.load(Compiler.java:7064)
at clojure.lang.Compiler.loadFile(Compiler.java:7020)
at clojure.main$load_script.invoke(main.clj:294)
at clojure.main$init_opt.invoke(main.clj:299)
at clojure.main$initialize.invoke(main.clj:327)
at clojure.main$null_opt.invoke(main.clj:362)
at clojure.main$main.doInvoke(main.clj:440)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:419)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.main.main(main.java:37)
Caused by: java.lang.RuntimeException: No such var: db/get-user
at clojure.lang.Util.runtimeException(Util.java:219)
at clojure.lang.Compiler.resolveIn(Compiler.java:6848)
at clojure.lang.Compiler.resolve(Compiler.java:6818)
at clojure.lang.Compiler.analyzeSymbol(Compiler.java:6779)
at clojure.lang.Compiler.analyze(Compiler.java:6343)
... 72 more
Compilation failed: Subprocess failed
我想我可能有一對夫婦在這裏,我並不需要加載的東西,但我project.clj文件看起來像這樣:
(defproject guestbook "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:dependencies [[org.clojure/clojure "1.5.1"]
[compojure "1.1.6"]
[hiccup "1.0.5"]
[ring-server "0.3.1"]
[lein-light-nrepl "0.0.15"]
[org.clojure/clojurescript "0.0-2156"]
[org.clojure/java.jdbc "0.2.3"]
[org.xerial/sqlite-jdbc"3.7.2"]
[lib-noir "0.8.0"]]
:repl-options {:nrepl-middleware [lighttable.nrepl.handler/lighttable-ops]}
:plugins [[lein-ring "0.8.7"]
[lein-ancient "0.5.4"]]
:ring {:handler guestbook.handler/app
:init guestbook.handler/init
:destroy guestbook.handler/destroy}
:aot :all
:profiles
{:production
{:ring
{:open-browser? false, :stacktraces? false, :auto-reload? false}}
:dev
{:dependencies [[ring-mock "0.1.5"] [ring/ring-devel "1.2.1"]]}})
home文件:
(ns guestbook.routes.home
(:require [compojure.core :refer :all]
[guestbook.views.layout :as layout]
[hiccup.form :refer :all]
[guestbook.models.db :as db]
[noir.session :as session]))
(defn format-time [timestamp]
(-> "dd/MM/yyyy"
(java.text.SimpleDateFormat.)
(.format timestamp)))
(defn home []
(layout/common [:h1 "Guestbook"]
[:p "Welcome to my guestbook"]
[:hr]
[:form]
[:p "name"]
[:input]
[:p "Message"]
[:textarea {:rows 10 :cols 40}]))
(defn show-guests []
[:ul.guests
(for [{:keys [message name timestamp]} (db/read-guests)]
[:li
[:blockquote message]
[:p "-" [:cite name]]
[:time (format-time timestamp)]])])
(defn home [& [name message error]]
(layout/common
[:h1 "Guestbook " (session/get :user)]
[:p "Welcome to my guestbook"]
[:p error]
(show-guests)
[:hr]
(form-to [:post "/"]
[:p "Name:" (text-field "name" name)]
[:p "Message:" (text-area {:rows 10 :cols 40} "message" message)]
(submit-button "comment"))))
(defn save-message [name message]
(cond
(empty? name)
(home name message "You forgot to leave a name, dumbass.")
(empty? message)
(home name message "Don't you have something to say?")
:else
(do
(db/save-message name message)
(home))))
(defroutes home-routes
(GET "/" [] (home))
(POST "/" [name message] (save-message name message)))
處理程序:
(ns guestbook.handler
(:use compojure.core
ring.middleware.resource
ring.middleware.file-info
hiccup.middleware
guestbook.routes.home)
(:require [compojure.handler :as handler]
[compojure.route :as route]
[guestbook.models.db :as db]
[guestbook.routes.auth :refer [auth-routes]]))
(defn init []
(println "guestbook is starting")
(if-not (.exists (java.io.File. "./db.sq3"))
(db/create-guestbook-table)))
(defn destroy []
(println "guestbook is shutting down"))
(defroutes app-routes
(route/resources "/")
(route/not-found "Not Found"))
(def app
(-> (routes auth-routes home-routes app-routes)
(handler/site)
(wrap-base-url)))
數據庫:
(ns guestbook.models.db
(:require [clojure.java.jdbc :as sql])
(:import java.sql.DriverManager))
(def db {:classname "org.sqlite.JDBC",
:subprotocol "sqlite",
:subname "db.sq3"})
(defn create-guestbook-table []
(sql/with-connection
db
(sql/create-table
:guestbook
[:id "INTEGER PRIMARY KEY AUTOINCREMENT"]
[:timestamp "TIMESTAMP DEFAULT CURRENT_TIMESTAMP"]
[:name "TEXT"]
[:message "TEXT"])
(sql/do-commands "CREATE INDEX timestamp_index ON guestbook (timestamp)")))
(defn read-guests []
(sql/with-connection
db
(sql/with-query-results res
["SELECT * FROM guestbook ORDER BY timestamp DESC"]
(doall res))))
(defn save-message [name message]
(sql/with-connection
db
(sql/insert-values
:guestbook
[:name :message :timestamp]
[name message (new java.util.Date)])))
授權:
(ns guestbook.routes.auth
(:require [compojure.core :refer [defroutes GET POST]]
[guestbook.views.layout :as layout]
[hiccup.form :refer
[form-to label text-field password-field submit-button]]
[noir.response :refer [redirect]]
[noir.session :as session]
[noir.validation
:refer [rule errors? has-value? on-error]]
[noir.util.crypt :as crypt]
[guestbook.models.db :as db]))
(defn format-error [[error]]
[:p.error error])
(defn control [field name text]
(list (on-error name format-error)
(label name text)
(field name)
[:br]))
(defn registration-page []
(layout/common
(form-to [:post "/register"]
(control text-field :id "screen name")
(control password-field :pass "Password")
(control password-field :pass1 "Retype Password")
(submit-button "Create Account"))))
(defn login-page []
(layout/common
(form-to [:post "/login"]
(control text-field :id "screen name")
(control password-field :pass "Password")
(submit-button "login"))))
(defn handle-login [id pass]
(let [user (db/get-user id)]
(rule (has-value? id)
[:id "screen name is required"])
(rule (has-value? pass)
[:pass "password is required"])
(rule (and user (crypt/compare pass (:pass user)))
[:pass "invalid password"])
(if (errors? :id :pass)
(login-page)
(do
(session/put! :user id)
(redirect "/")))))
(defn handle-registration [id pass pass1]
(rule (= pass pass1)
[:pass "password was not retyped correctly"])
(if (errors? :pass)
(registration-page)
(do
(db/add-user-record {:id id :pass (crypt/encrypt pass)})
(redirect "/login"))))
(defroutes auth-routes
(GET "/register" [] (registration-page))
(POST "/register" [id pass pass1]
(handle-registration id pass pass1))
(GET "/login" [] (login-page))
(POST "/login" [id pass]
(handle-login id pass))
(GET "/logout" []
(layout/common
(form-to [:post "/logout"]
(submit-button "logout"))))
(POST "/logout" []
(session/clear!)
(redirect "/")))
可能有人請幫我解卡,所以我可以重新進入我的教程的擺動?此外,關於如何有效更新基於已棄用庫的代碼的任何提示都將有所幫助。我爲長時間的代碼表示歉意,但我仍然是一個noob,並不完全確定問題出在哪裏。我懷疑它必須對數據庫依賴關係做些什麼,因爲特定的sql/with-connection在我的谷歌搜索[org.clojure/java.jdbc「0.2.3」]依賴項中被棄用了,這是現在在版本0.3.3。
非常感謝!我調整了代碼以確保它與我在教程中的位置相匹配,並且似乎啓動了本地主機,但現在我正在瀏覽器中獲取該代碼! java.lang.ClassCastException clojure.lang.Var $沒有限制不能轉換到java.util.concurrent.Future ... (來源不明)\t ring.adapter.jetty.proxy $ org.eclipse.jetty .server.handler.AbstractHandler $ 0.handle ... – kurofune
無法排除只有那麼多信息的問題。 – deadghost
我在書籍網站上轉載了我的問題,並帶有一個展開的堆棧跟蹤: –
kurofune