jvm.require

dependency-aware namespace requiring for development

Retry a namespace require after discovering and loading a missing namespace dependency from the compiler error chain.

1    Overview

force-require is a development helper for namespaces that fail to reload because a referenced namespace has not yet been loaded. It follows missing-namespace errors, requires the dependency, and then returns through the original stack.

2    Walkthrough

2.1    Require a namespace

(require '[jvm.require :as jvm-require])

(jvm-require/force-require
 'example.application)

2.2    Use in a reload workflow

Call this helper when generating or rearranging namespaces during development. Normal application startup should generally continue to use ordinary require declarations so dependency problems remain explicit.

(doseq [namespace
        '[example.model
          example.service
          example.application]]
  (jvm-require/force-require namespace))

3    API



force-require ^

[ns] [ns stack]
Added 4.0

a more flexible require, reloading namespaces if errored

v 4.0
(defn force-require
  ([ns]
   (force-require ns []))
  ([ns stack]
   (let [parse-fn (fn [msg]
                    (if-let [ns-str (second (re-find #"namespace '(.*)' not found"
                                                     msg))]
                      (symbol ns-str)))
         ns-dep (try
                  (require ns :reload)
                  nil
                  (catch Throwable t
                    (if-let [cause (.getCause t)]
                      (if-let [ns-dep (parse-fn (.getMessage cause))]
                        ns-dep
                        (throw t))
                      (throw t))))]
     (cond ns-dep
           (do (env/p :REQUIRING ns-dep)
               (recur ns-dep (cons ns stack)))

           (not-empty stack)
           (recur (first stack) (rest stack))
           
           :else
           (env/p :DONE)))))
link
(force-require 'jvm.require) => nil