Using Pedestal with Trapperkeeper

Mitchel Kuijpers

Mitchel Kuijpers

Published: 13 April, 2015

Intro

I am currently working on Dash, developed with Clojure. For this project I recently started using two libraries together: Pedestal and Trapperkeeper. Clojure enables me to pick and combine the libraries I see fit, which is one of the reasons I enjoy writing Clojure. But figuring out how to combine libraries can sometimes be tricky, I had to fiddle a bit before I had this working. Hopefully this blogpost will save someone else some time.

Trapperkeeper uses Compojure by default in their examples, which is also a fine library but I prefer Pedestal. In this blogpost I will show how you can replace Compojure by Pedestal. If you just want to see how to do it, see the example repository on Github. You can also see the commit that replaces Compojure by Pedestal here, this commit is made to a fresh trapperkeeper project. By fresh, I mean created by running

lein new trapperkeeper nl.avisi.trapperkeeper-pedestal.example

Replace

I used the webrouting service of Trapperkeeper, this has the added value that your routes are configurable:

web-router-service: {
"nl.avisi.trapperkeeper-pedestal.example-web-service/hello-web-service": "/hello"
}

/dev-resources/config.conf

In the example above there is a hello-web-service that gets mounted on the path /hello. It is not necessary to make any changes here because I keep the path the same. We only need to change the implementation of the hello-web-service.

This was the hello-web-service before I integrated Pedestal:

(trapperkeeper/defservice hello-web-service
[[:ConfigService get-in-config]
[:WebroutingService add-ring-handler get-route]
HelloService]
(init [this context]
(log/info "Initializing hello webservice")
(let [url-prefix (get-route this)]
(add-ring-handler
this
(compojure/context url-prefix []
(core/app (tk-services/get-service this :HelloService))))
(assoc context :url-prefix url-prefix)))

/src/nl/avisi/trapperkeeper_pedestal/example_web_service.clj

The interesting part is the add-ring-handler function, which adds a ring handler to the previously configured web-routers-service. This would mean the ring handler get's mounted on /hello.

The next step is removing the Compojure routes and replacing it for Pedestal. The first thing we need to do is add some routes:

(defroutes routes [[["/*who" {:get index}
^:interceptors [get-greeting http/html-body]]]])

This code defines a route which will match "/" and for example "/world". You'll also see I defined some interceptors. If you don't know what they are you can read the documentation about interceptors, but for now you can think of them as middleware (only much cooler).

Let's actually bootstrap Pedestal, I created a slimmed down version for this example. See the full version here:

(trapperkeeper/defservice hello-web-service
[[:WebroutingService add-servlet-handler]]
(init [this context]
(log/info "Initializing hello webservice")
(let [service {:env :prod
::http/routes routes
::http/resource-path "public"}]
(add-servlet-handler this (::http/servlet (http/create-servlet service))))
context))

/src/nl/avisi/trapperkeeper_pedestal/example_web_service.clj

We define a hello-web-service and instead of using the add-ring-handler, we use add-servlet-handler and we call from the io.pedestal.http namespace http/create-servlet this expects a service definition with a routes property. And this is all the work you need to bootstrap pedestal in trapperkeeper.

If you want to run this example yourself make sure you have Leiningen installed and then clone the repo:

git clone https://github.com/avisi/trapperkeeper-pedestal.git

Then to run it:

cd trapperkeeper-pedestal
lein tk

After a while you should see something like this:

2015-03-10 15:46:38,927 INFO  [p.t.s.w.jetty9-service] Initializing web server(s).
2015-03-10 15:46:38,934 INFO [n.a.t.example-service] Initializing hello service
2015-03-10 15:46:38,935 INFO [n.a.t.example-web-service] Initializing hello webservice
2015-03-10 15:46:38,964 INFO [p.t.s.w.jetty9-service] Starting web server(s).
2015-03-10 15:46:39,084 INFO [p.t.s.w.jetty9-core] Starting web server.
2015-03-10 15:46:39,192 INFO [n.a.t.example-service] Starting hello service
2015-03-10 15:46:39,194 INFO [n.a.t.example-web-service] Hello web service started; visit http://localhost:8080/hello/ to check it out!

If you open http://localhost:8080/hello/world it should say hello world. You can change the world part for anything you want and it will greet you. I know, it's very impressive!

If you know a better way or have some suggestions, feel free to tweet to me @mitchelkuijpers or leave a comment below.

Did you enjoy reading?

Share this blog with your audience!