Не удается поймать исключение в приложении Clojure Ring

Я работаю над своим приложением для покупок и пытаюсь создать собственный обработчик исключений, но есть кое-что еще, что ловит их, прежде чем я доберусь до них!

Вот мой обработчик

(defn wrap-fallback-exception
    [handler]
    (fn [request]
        (try+
            (handler request)
            (catch [:type :test] {:keys [msg]}
                (println "## Test Exception:" msg))
            (catch Exception e (println "## Exception"))
            (catch Throwable e
                (println "## Throwable:" (.getMessage e) e)))))

Вот мой стек

(-> all-routes
        (wrap-anti-forgery)
        (friend/authenticate {
             :unauthorized-handler unauth-handler
             :credential-fn        (partial cred get-user)
             :workflows            [(workflows/interactive-form)]})
        (wrap-session {:store (->ShopStore )})
        (wrap-keyword-params)
        (wrap-params)
        (wrap-cookies)
        (wrap-fallback-exception)
        (run-server {:port 3000}))

Я выполняю тест в одной из моих функций вызова

(throw+ (ex-info "TEST" {:type :test}))

И полученный результат выглядит так

Sun Apr 01 15:57:29 CEST 2018 [worker-4] ERROR - GET /user/home
clojure.lang.ExceptionInfo: TEST {:type :test}
    at clojure.core$ex_info.invokeStatic(core.clj:4739)
    at clojure.core$ex_info.invoke(core.clj:4739)
    at shop2.views.home$mk_proj_row.invokeStatic(home.clj:90)
    at shop2.views.home$mk_proj_row.invoke(home.clj:88)
    at clojure.lang.AFn.applyToHelper(AFn.java:154)
    at clojure.lang.AFn.applyTo(AFn.java:144)
    at orchestra.spec.test$spec_checking_fn$fn__1372.doInvoke(test.clj:123)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.core$map$fn__5587.invoke(core.clj:2747)
    at clojure.lang.LazySeq.sval(LazySeq.java:40)
    at clojure.lang.LazySeq.seq(LazySeq.java:49)
    at clojure.lang.RT.seq(RT.java:528)
    at clojure.core$seq__5124.invokeStatic(core.clj:137)
    at clojure.core$print_sequential.invokeStatic(core_print.clj:53)
    at clojure.core$fn__7019.invokeStatic(core_print.clj:174)
    at clojure.core$fn__7019.invoke(core_print.clj:174)
    at clojure.lang.MultiFn.invoke(MultiFn.java:233)
    at clojure.core$pr_on.invokeStatic(core.clj:3666)
    at clojure.core$pr_on.invoke(core.clj:3660)
    at clojure.core$print_sequential.invokeStatic(core_print.clj:66)
    at clojure.core$fn__7039.invokeStatic(core_print.clj:225)
    at clojure.core$fn__7039.invoke(core_print.clj:225)
    at clojure.lang.MultiFn.invoke(MultiFn.java:233)
    at clojure.core$pr_on.invokeStatic(core.clj:3666)
    at clojure.core$pr_on.invoke(core.clj:3660)
    at clojure.core$print_sequential.invokeStatic(core_print.clj:66)
    at clojure.core$fn__7039.invokeStatic(core_print.clj:225)
    at clojure.core$fn__7039.invoke(core_print.clj:225)
    at clojure.lang.MultiFn.invoke(MultiFn.java:233)
    at clojure.core$pr_on.invokeStatic(core.clj:3666)
    at clojure.core$pr_on.invoke(core.clj:3660)
    at clojure.core$print_sequential.invokeStatic(core_print.clj:66)
    at clojure.core$fn__7039.invokeStatic(core_print.clj:225)
    at clojure.core$fn__7039.invoke(core_print.clj:225)
    at clojure.lang.MultiFn.invoke(MultiFn.java:233)
    at clojure.core$pr_on.invokeStatic(core.clj:3666)
    at clojure.core$pr_on.invoke(core.clj:3660)
    at clojure.core$print_sequential.invokeStatic(core_print.clj:66)
    at clojure.core$fn__7019.invokeStatic(core_print.clj:174)
    at clojure.core$fn__7019.invoke(core_print.clj:174)
    at clojure.lang.MultiFn.invoke(MultiFn.java:233)
    at clojure.core$pr_on.invokeStatic(core.clj:3666)
    at clojure.core$pr_on.invoke(core.clj:3660)
    at clojure.core$print_sequential.invokeStatic(core_print.clj:66)
    at clojure.core$fn__7019.invokeStatic(core_print.clj:174)
    at clojure.core$fn__7019.invoke(core_print.clj:174)
    at clojure.lang.MultiFn.invoke(MultiFn.java:233)
    at clojure.core$pr_on.invokeStatic(core.clj:3666)
    at clojure.core$pr_on.invoke(core.clj:3660)
    at clojure.core$print_sequential.invokeStatic(core_print.clj:66)
    at clojure.core$fn__7039.invokeStatic(core_print.clj:225)
    at clojure.core$fn__7039.invoke(core_print.clj:225)
    at clojure.lang.MultiFn.invoke(MultiFn.java:233)
    at clojure.core$pr_on.invokeStatic(core.clj:3666)
    at clojure.core$pr_on.invoke(core.clj:3660)
    at clojure.lang.Var.invoke(Var.java:385)
    at clojure.lang.RT.print(RT.java:1877)
    at clojure.lang.RT.printString(RT.java:1857)
    at clojure.lang.APersistentVector.toString(APersistentVector.java:26)
    at org.httpkit.HttpUtils.bodyBuffer(HttpUtils.java:112)
    at org.httpkit.HttpUtils.HttpEncode(HttpUtils.java:442)
    at org.httpkit.server.HttpHandler.run(RingHandler.java:101)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

Исключение никогда не поймано моим обработчиком! Я пробовал каждую версию, о которой я могу думать, без удачи:-(Кто ловит это? И как я могу остановить это?

С уважением Сорен

1 ответ

Ваш обработчик возвращается успешно, без исключения. Возвращаемое им значение, по-видимому, представляет собой многоуровневый вектор, содержащий глубоко внутри себя ленивую последовательность. Когда Ring пытается распечатать эту ленивую последовательность, принудительно вызывает эту последовательность mk-proj-row, который бросает исключение. Важно, что это происходит после того, как ваш обработчик полностью завершил работу, то есть обработчик исключений больше не действует.

Я сомневаюсь, что вы действительно хотите зашифровать гигантский вектор в качестве выходных данных: я полагаю, вы забыли использовать Hiccup для преобразования этого в HTML или что-то еще для преобразования его в JSON. Вы, вероятно, должны иметь некоторое промежуточное программное обеспечение, которое выполняет это преобразование, прежде чем вернуться в Ring; если вы поставите это промежуточное программное обеспечение перед вашим wrap-fallback-exception промежуточное программное обеспечение, тогда лень больше не будет проблемой, потому что ленивая последовательность будет реализована внутри средства рендеринга Hiccup (или чего-то еще), а не в Ring после того, как все ваши обработчики закончили.

Другие вопросы по тегам