Ok, after much 'googling' and experimentation I seem to have come up with some reasonable solutions to my problems.
I'm very new to Clojure and I followed along with the example from this excellent video tutorial.
Then I amended the example because I wanted to try and deploy the app to Tomcat
.
That's when the trouble started. As I stated in my question, if I ran the app via lein ring server
whilst I was developing, then all was good. But I wanted to deploy my app to Tomcat
and in order to do that I needed to build an uberwar
.
The lein ring uberwar webdev.war
command is just what I need.
Once I deployed the app to Tomcat
the following problems occurred
- The
css
andjs
files stopped being served. - The forms were not posting back to the correct URL
- The redirects after form posts were also attempting to redirect to the incorrect URL
What I hadn't noticed before was that when an uberwar
is built then a :context
key is added to the request
map. (I think you also have to use the wrap-base-url
middleware in order for the key to get added to the request map)
In order to get the css and js files served I needed to use include-css
and include-js
functions from the hiccup.page
namespace.
So instead of using
[:script {:src "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"}]
[:script {:src "/bootstrap/js/bootstrap.min.js"}]
in my views.clj. I used
(include-css "/bootstrap/css/bootstrap.min.css")
(include-js "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"
"/bootstrap/js/bootstrap.min.js")
These functions obviously respect the :context
key and my css
and js
files get served correctly.
The next issue was my forms were not posting back to the correct URL. So once again I needed to change the code in my views. I now needed to define my forms using the form/form-to
from the hiccup.form
namespace.
(form/form-to [:post (str "/items/" id)
These functions are also obviously :context
aware.
Finally I needed to fix the redirects
after the form posts. To achieve this I needed to change the handler signatures of handle-create-item, handle-delete-item and handle-update-item
and the appropriate route definitions so that they passed the request
map in addition to the other parameters the handlers required. Then I just created a little helper function
defn items-list [req]
(str (:context req) "/items"))
that plucked out the :context
from the request
map and prepended it to the route.
Once I made those alterations my app now runs correctly locally via lein ring server
when I'm developing and also when its deployed to a Tomcat
server.
I hope this might help others faced with similar issues. The complete source code can be found here at my github account