File: Reloaded-Pattern.md

package info (click to toggle)
trapperkeeper-clojure 4.0.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 964 kB
  • sloc: sh: 189; xml: 73; makefile: 25; java: 5
file content (59 lines) | stat: -rw-r--r-- 2,421 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# Using the "Reloaded" Pattern

[Stuart Sierra's "reloaded" workflow](http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded) has become very popular in the clojure world of late; and for good reason, it's an awesome and super-productive way to do interactive development in the REPL, and it also helps encourage code modularity and minimizing mutable state.  He has some [example code](https://github.com/stuartsierra/component#reloading) that shows some utility functions to use in the REPL to interact with your application.

Trapperkeeper was designed with this pattern in mind as a goal.  Thus, it's entirely possible to write some very similar code that allows you to start/stop/reload your app in a REPL:

```clj
(ns examples.my-app.repl
  (:require [puppetlabs.trapperkeeper.services.webserver.jetty9-service
              :refer [jetty9-service]]
            [examples.my-app.services
              :refer [count-service foo-service baz-service]]
            [puppetlabs.trapperkeeper.core :as tk]
            [puppetlabs.trapperkeeper.app :as tka]
            [clojure.tools.namespace.repl :refer (refresh)]))

;; a var to hold the main `TrapperkeeperApp` instance.
(def system nil)

(defn init []
  (alter-var-root #'system
                  (fn [_] (tk/build-app
                            [jetty9-service
                             count-service
                             foo-service
                             baz-service]
                            {:global
                              {:logging-config "examples/my_app/logback.xml"}
                             :webserver {:port 8080}
                             :example   {:my-app-config-value "FOO"}})))
  (alter-var-root #'system tka/init)
  (tka/check-for-errors! system))

(defn start []
  (alter-var-root #'system
                  (fn [s] (if s (tka/start s))))
  (tka/check-for-errors! system))

(defn stop []
  (alter-var-root #'system
                  (fn [s] (when s (tka/stop s)))))

(defn go []
  (init)
  (start))

(defn context []
  @(tka/app-context system))

;; pretty print the entire application context
(defn print-context []
  (clojure.pprint/pprint (context)))

(defn reset []
  (stop)
  (refresh :after 'examples.my-app.repl/go))
```

For a working example, see the `repl` namespace in the [jetty9 example app](https://github.com/puppetlabs/trapperkeeper-webserver-jetty9/tree/master/examples/ring_app).