duct
duct copied to clipboard
No method in method in multimethod 'init-key' for dispatch value:
Hi! I'm trying to convert the template project to boot but when I try to build a jar of the main class I get this error on runtime
Exception in thread "main" clojure.lang.ExceptionInfo: Error on key :duct.profile/base when building system {:reason :integrant.core/build-threw-exception, :system {}, :function #object[clojure.lang.MultiFn 0x5972d253 "clojure.lang.MultiFn@5972d253"], :key :duct.profile/base, :value {:duct.core/project-ns redblack-duct, :duct.router/ataraxy {:routes {[:get "/example"] [:redblack-duct.handler/example]}}, :redblack-duct.handler/example {}}}
at integrant.core$build_exception.invokeStatic(core.cljc:283)
at integrant.core$build_exception.invoke(core.cljc:282)
at integrant.core$try_build_action.invokeStatic(core.cljc:294)
at integrant.core$try_build_action.invoke(core.cljc:291)
at integrant.core$build_key.invokeStatic(core.cljc:300)
at integrant.core$build_key.invoke(core.cljc:296)
at clojure.core$partial$fn__5841.invoke(core.clj:2632)
at clojure.core.protocols$fn__8159.invokeStatic(protocols.clj:168)
at clojure.core.protocols$fn__8159.invoke(protocols.clj:124)
at clojure.core.protocols$fn__8114$G__8109__8123.invoke(protocols.clj:19)
at clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:31)
at clojure.core.protocols$fn__8146.invokeStatic(protocols.clj:75)
at clojure.core.protocols$fn__8146.invoke(protocols.clj:75)
at clojure.core.protocols$fn__8088$G__8083__8101.invoke(protocols.clj:13)
at clojure.core$reduce.invokeStatic(core.clj:6828)
at clojure.core$reduce.invoke(core.clj:6810)
at integrant.core$build.invokeStatic(core.cljc:321)
at integrant.core$build.invoke(core.cljc:303)
at integrant.core$init.invokeStatic(core.cljc:418)
at integrant.core$init.invoke(core.cljc:410)
at duct.core$build_config.invokeStatic(core.clj:182)
at duct.core$build_config.invoke(core.clj:173)
at duct.core$prep_config.invokeStatic(core.clj:193)
at duct.core$prep_config.invoke(core.clj:184)
at duct.core$exec_config.invokeStatic(core.clj:225)
at duct.core$exec_config.invoke(core.clj:213)
at redblack_duct.main$_main.invokeStatic(main.clj:12)
at redblack_duct.main$_main.doInvoke(main.clj:7)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.AFn.applyToHelper(AFn.java:152)
at clojure.lang.RestFn.applyTo(RestFn.java:132)
at redblack_duct.main.main(Unknown Source)
Caused by: java.lang.IllegalArgumentException: No method in multimethod 'init-key' for dispatch value: :duct.profile/base
at clojure.lang.MultiFn.getFn(MultiFn.java:156)
at clojure.lang.MultiFn.invoke(MultiFn.java:233)
at integrant.core$try_build_action.invokeStatic(core.cljc:292)
... 29 more
I did comment out the db stuff from the config.edn temporarily like so
{:duct.profile/base
{:duct.core/project-ns redblack-duct
:duct.router/ataraxy
{:routes {[:get "/example"] [:redblack-duct.handler/example]}}
:redblack-duct.handler/example{}
;; {:db #ig/ref :duct.database/sql}
}
:duct.profile/dev #duct/include "dev"
:duct.profile/local #duct/include "local"
:duct.profile/prod {}
:duct.module/logging {}
:duct.module.web/api
{}
:duct.module/cljs
{:main redblack-duct.client}
;; :duct.module/sql
;; {}
:duct.module.web/site
{}}
What does your redblack_duct.main
namespace look like? Are you requiring duct.core
? If you are, what does your dependency tree look like?
The namespace looks like:
(ns redblack-duct.main
(:gen-class)
(:require [duct.core :as duct]))
(duct/load-hierarchy)
(defn -main [& args]
(let [keys (or (duct/parse-keys args) [:duct/daemon])
profiles [:duct.profile/prod]]
(-> (duct/resource "redblack_duct/config.edn")
(duct/read-config)
(duct/exec-config profiles keys))))
That seems fine - it loads in duct.core
where :duct.profile/base
is defined. So the other thing to check is your dependency tree to ensure you have the right version. In Leiningen that's lein deps :tree
, but I don't know what it would be under Boot.
Dependencies look up to date
Are you building an uberjar? If so, have you correctly merged the duct_hierarchy.edn
resources?
Hmm I'm not sure. It's in resources but I'm sure if it's being included. Do you know how I could check?
If you haven't explicitly written code to account for it, that's probably your issue. When you're combining resources into an uberjar, you need to be careful about resources that share the same path.
In the Leiningen plugin, I've added some middleware to merge the duct_hierarchy.edn
resources when building the uberjar. You'll need to do something similar in Boot. I assume it has some equivalent mechanism for handling uberjar resource merges.
I think I figured out how to include the duct_hierarchy.edn file but now I'm getting a stranger runtime exception
Exception in thread "main" java.lang.NoClassDefFoundError: clojure/lang/Var
at redblack_duct.main.<clinit>(Unknown Source)
Caused by: java.lang.ClassNotFoundException: clojure.lang.Var
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 1 more
With duct_hierarchy.edn
you need to use the Boot equivalent to Leiningen's :uberjar-merge-with
key. I'm not sure how you've managed to exclude clojure.lang.Var
- that class should be in the Clojure dependency!
I just had a quick look at Boot. It has a :mergers
option for uberjars, so you should be able to add: [ #"duct_hierarchy.clj$" into-merger]
to your mergers in order to get it working correctly, assuming that you haven't discovered that already.
That gives me
/nix/store/zavn4np1jvm79f0rafkv0p1mrag09qkz-bash-4.4-p23/bin/bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
Boot.main Boot.java: 257
...
boot.App.main App.java: 500
boot.App.runBoot App.java: 407
org.projectodd.shimdandy.impl.ClojureRuntimeShimImpl.invoke ClojureRuntimeShimImpl.java: 145
org.projectodd.shimdandy.impl.ClojureRuntimeShimImpl.invoke ClojureRuntimeShimImpl.java: 154
...
boot.main/-main main.clj: 216
boot.main/-main/fn main.clj: 216
clojure.core/load-string core.clj: 4089
clojure.core/load-reader core.clj: 4087
...
java.lang.RuntimeException: Unable to resolve symbol: into-merger in this context
clojure.lang.ExceptionInfo: Unable to resolve symbol: into-merger in this context
line: 32
and without into-merger
java.lang.Thread.run Thread.java: 748
java.util.concurrent.ThreadPoolExecutor$Worker.run ThreadPoolExecutor.java: 624
1 (set-env!
java.util.concurrent.ThreadPoolExecutor.runWorker ThreadPoolExecutor.java: 1149
java.util.concurrent.FutureTask.run FutureTask.java: 266
...
clojure.core/binding-conveyor-fn/fn core.clj: 2030
boot.core/boot/fn core.clj: 1033
...
boot.core/construct-tasks core.clj: 973
boot.core/construct-tasks core.clj: 995
clojure.core/apply core.clj: 665
...
boot.user$eval3883$fn__3884.doInvoke : 55
...
boot.user$eval3857$fn__3858$fn__3859.doInvoke : 32
clojure.core/apply core.clj: 665
...
boot.task.built-in/eval2830/fn built_in.clj: 658
...
boot.cli/assert-type cli.clj: 78
clojure.core/mapv core.clj: 6903
clojure.core/into core.clj: 6895
clojure.core/reduce core.clj: 6828
clojure.core.protocols/fn/G protocols.clj: 13
clojure.core.protocols/fn protocols.clj: 75
clojure.core.protocols/seq-reduce protocols.clj: 24
clojure.core/seq core.clj: 137
...
clojure.core/map/fn core.clj: 2760
boot.cli/assert-type cli.clj: 78
clojure.core/mapv core.clj: 6903
clojure.core/into core.clj: 6895
clojure.core/reduce core.clj: 6828
clojure.core.protocols/fn/G protocols.clj: 13
clojure.core.protocols/fn protocols.clj: 75
clojure.core.protocols/seq-reduce protocols.clj: 24
clojure.core/seq core.clj: 137
...
clojure.core/map/fn core.clj: 2757
clojure.core/seq core.clj: 137
...
java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.util.regex.Pattern
clojure.lang.ExceptionInfo: Don't know how to create ISeq from: java.util.regex.Pattern
line: 68
You probably need to require the namespace for into-merger
first...
Hmm I can't find what package it's in..
It's in the boot.pod
namespace. You can just search for the function on Github.
Oh sweet I didn't know that! Thanks!