I'm using Clojure to build a sample web app. I'm using the lein ring
plugin and compojure
for routing.
When I run the app using lein ring server
everything works fine. I can browse to localhost:3000/items and everything looks good all css & js is loaded.
However when I build an uberwar (lein ring uberwar webdev.war
) and deploy that to Tomcat
the routing is wrong.
Once deployed I browse to localhost:8080/webdev/items
The css/js files don't get loaded because the path to them does not include the context "webdev"
.
Similarly my forms defined in Hiccup
are trying to post back to /items
which again does not include the context webdev
.
Here's my project.clj, core.clj and views.clj
Project.clj:
(defproject webdev "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.5.1"]
[ring "1.2.2"]
[hiccup "1.0.5"]
[compojure "1.1.6"]
[org.clojure/java.jdbc "0.3.3"]
[postgresql/postgresql "9.1-901.jdbc4"]]
:plugins [[lein-ring "0.8.10"]]
:ring {:init webdev.core/create-db-schema
:handler webdev.core/app
:servlet-path-info? true
}
)
Core.clj
(ns webdev.core
(:require [webdev.item.model :as items])
(:require [webdev.item.handler :refer [handle-index-items
handle-create-item
handle-delete-item
handle-update-item]])
(:require
[hiccup.middleware :refer [wrap-base-url]]
[ring.middleware.reload :refer [wrap-reload]]
[ring.middleware.params :refer [wrap-params]]
[ring.middleware.resource :refer [wrap-resource]]
[ring.middleware.file-info :refer [wrap-file-info]]
[compojure.core :refer [defroutes ANY GET POST PUT DELETE]]
[compojure.route :as route]
[compojure.handler :as handler]
[ring.handler.dump :refer [handle-dump]]))
(defn greet [req]
{:status 200
:body "Hello, World!!!!!!!!!!!!!"
:headers {}})
(defroutes routes
(GET "/" [] greet)
(ANY "/request" [] handle-dump)
(GET "/items" [] handle-index-items)
(POST "/items" [& params] (handle-create-item params))
(DELETE "/items/:item-id" [item-id] (handle-delete-item item-id))
(PUT "/items/:item-id" [& params] (handle-update-item params))
(route/resources "/" {:root "static"})
(route/not-found "Page not found."))
(defn create-db-schema []
(items/create-table))
(defn wrap-server-response [hndlr]
(fn [req]
(let [response (hndlr req)]
(assoc-in response [:headers "Server:"] "my-server"))))
(def sim-methods {"PUT" :put
"DELETE" :delete})
(defn wrap-simulated-methods [hndlr]
(fn [req]
(if-let [method (and (= :post (:request-method req))
(sim-methods (get-in req [:params "_method"])))]
(hndlr (assoc req :request-method method))
(hndlr req))))
(def app-routes
(wrap-base-url
(wrap-file-info
(wrap-server-response
(wrap-params
(wrap-simulated-methods routes))))))
(def app
(handler/site app-routes))
View.clj
(ns webdev.item.view
(:require [hiccup.page :refer [html5]]
[hiccup.core :refer [html h]]))
(defn new-item []
(html
[:form.form-horizontal
{:method "POST" :action "/items"}
[:div.form-group
[:label.control-label.col-sm-2 {:for :name-input}
"Name"]
[:div.col-sm-10
[:input#name-input.form-control
{:name :name :placeholder "Name"}]]]
[:div.form-group
[:label.control-label.col-sm-2 {:for :desc-input}
"Description"]
[:div.col-sm-10
[:input#desc-input.form-control
{:name :description :placeholder "Description"}]]]
[:div.form-group
[:div.col-sm-offset-2.col-sm-10
[:input.btn.btn-primary
{:type :submit
:value "New item"}]]]]))
(defn delete-item-form [id]
(html
[:form.form-horizontal
{:method "POST" :action (str "/items/" id)}
[:div.form-group
[:input {:type :hidden
:name "_method"
:value "DELETE"}]
[:div.col-sm-offset-2.col-sm-10
[:input.btn.btn-danger.btn-xs
{:type :submit
:value "Delete" }]]]]))
(defn update-checked-form [id checked]
(html
[:form.form-horizontal
{:method "POST" :action (str "/items/" id)}
[:div.form-group
[:input {:type :hidden
:name "_method"
:value "PUT"}]
[:input {:type :hidden
:name "checked"
:value (str (not checked))}]
[:div.col-sm-offset-2.col-sm-10
[:input.btn.btn-primary.btn-xs
{:type :submit
:value (if checked "Done" "To-do")}]]]]))
(defn items-page [items]
(html5 {:lang :en}
[:head
[:title "CLOJURE Web Dev Tutorial"]
[:meta {:name :viewport :content "width=device-width, initial-scale=1.0"}]
[:link {:href "/bootstrap/css/bootstrap.min.css"
:rel :stylesheet}]]
[:body
[:div.container
[:h1 "My Items"]
[:div.row
(if (seq items)
[:table.table.table-striped
[:thead
[:tr
[:th "Name"]
[:th "Description"]
[:th.col-sm-2]
[:th.col-sm-2]]]
[:tbody
(for [i items]
[:tr
[:td (h (:name i))]
[:td (h (:description i))]
[:td (update-checked-form (:id i) (:checked i))]
[:td (delete-item-form (:id i))]])]]
[:div.col-sm-offset-1 "There are no items."])]
[:div.col-sm-6
[:h2 "Create a new item"]
(new-item)]]
[:script {:src "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"}]
[:script {:src "/bootstrap/js/bootstrap.min.js"}]]))
I saw this related question but I didn't seem to help
How can I fix this problem?