clojurecompojure

updated atom value not used in compojure route


I have a (routes (route/not-found)) definition with value derived from an (atom). Though I've updated the atom, the routing retains the initial value. This is similiar to Dynamic handler update in Clojure Ring/Compojure REPL but I'm having a hard time understanding what needs to be de/referenced where.

(ns mveroute
  (:require 
   [org.httpkit.server :as srv]
   [compojure.core :as cmpj]
   [compojure.route :as route]
   [clj-http.client :as client])
  (:gen-class))

(def my-atom (atom "foobar"))

(def app
  (cmpj/routes
   (route/not-found {:status 400 :body @my-atom})))

(defn -main [& args]
  (reset! my-atom "hello world")

  (srv/run-server #'app {:port 8005})

  ;; "hello world" as expected
  (println @my-atom)

  ;; still "foobar" but wanted "hello world" 
  (-> "http://localhost:8005"
      (client/get   {:throw-exceptions? false})
      :body
      println))

I thought warp-routes might have come to the rescue. But not how I've used it.

(defn atom-body [] {:status 200 :body @my-atom})

(cmpj/defroutes wrap-found
  (route/not-found (atom-body)))

(def app
  (cmpj/wrap-routes #'wrap-found {}))

The ultimate goal is a simple cli application that can set the resource/html root directory with command line arguments.


Solution

  • Try something like the following:

    (defn not-found-fn
      [req]
      {:status 400 :body "not found again!"})
    
    (def app
      (cmpj/routes
        (route/not-found not-found-fn)))
    

    So inside of not-found-fn, you can construct the :body string any way you like. You could also have the string stored in an atom which is dereferenced by not-found-fn.


    Side note:

    Please see the following to clarify when you should use a Var object instead of just a symbol in your code:

    When to use a Var instead of a function?