Fork me on GitHub
#reitit
<
2022-06-24
>
Otto Nascarella14:06:54

hello folks, I am starting to use reitit with malli I am currently looking into a way to have the coercion run, but instead of breaking in case something is off, to report it. so we were doing something like this:

(defn- safe-coercer [coercion-type original-coercer]
  (fn [value format]
    (let [result (original-coercer value format)]
      (if (coercion/error? result)
        (do (log/errorf (str coercion-type " coercion failed with data %s")
                        (into {} result))
            value)
        result))))

(defn- create-safe-coercion [original-coercion]
  ^{:type ::coercion/coercion}
  (reify coercion/Coercion
    (-get-name [_this]
      (coercion/-get-name original-coercion))
    (-get-options [_this]
      (coercion/-get-options original-coercion))
    (-get-apidocs [_this specification data]
      (coercion/-get-apidocs original-coercion specification data))
    (-compile-model [_this model name]
      (coercion/-compile-model original-coercion model name))
    (-open-model [_this model] (coercion/-open-model original-coercion model))
    (-encode-error [_this error] (coercion/-encode-error original-coercion error))
    (-request-coercer [_this type model]
      (safe-coercer "request" (coercion/-request-coercer original-coercion type model)))
    (-response-coercer [_this model]
      (safe-coercer "response" (coercion/-response-coercer original-coercion model)))))
(def coercion-safe
  (create-safe-coercion 
    (reitit.coercion.malli/create
       (assoc-in reitit.coercion.malli/default-options [:transformers :body :default]
             reitit.coercion.malli/string-transformer-provider))))

🧵 1
Otto Nascarella14:06:42

so… it runs OK in dev time, but it breaks when generating the uberjar: it says that -request-coercer is not being implemented…

Otto Nascarella14:06:55

any clues? a better way to achieve the same result?

rolt15:06:11

you could add an exception handler middleware / interceptor and handle stuff there. I think you have everything in the ex-data

ikitommi12:06:10

@U5B8QSSC9 AOT is a beast, you might end up having protocol instances and definitions compiled with different ClassLoaders(?), so they don’t work together. In your case, the coercion-safe is mostly likely AOT-compiled. 2 good options: 1. AOT-compile as little as possible, e.g. a separate minimal main where you do a requiring-resolve for the actual code -> dynamic linking, slower startup, just works 2. make the coercion-safe a defn, so the instance is not AOT-compiled, just a function to generate it

👀 1
ikitommi12:06:48

a “correct” main with integrant would look like:

(ns example.main
  (:gen-class)
  (:require [clojure.tools.logging :as log]
            [integrant.core :as ig]))

(defn -main []
  (log/info "System starting...")
  (let [config ((requiring-resolve 'example.integrant/system-config))]
    (ig/init config)))