duct icon indicating copy to clipboard operation
duct copied to clipboard

No method in method in multimethod 'init-key' for dispatch value:

Open 0x4d6165 opened this issue 4 years ago • 15 comments

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
 {}}

0x4d6165 avatar Nov 18 '19 04:11 0x4d6165

What does your redblack_duct.main namespace look like? Are you requiring duct.core? If you are, what does your dependency tree look like?

weavejester avatar Nov 18 '19 04:11 weavejester

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))))

0x4d6165 avatar Nov 18 '19 04:11 0x4d6165

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.

weavejester avatar Nov 18 '19 12:11 weavejester

Dependencies look up to date

0x4d6165 avatar Nov 18 '19 18:11 0x4d6165

Are you building an uberjar? If so, have you correctly merged the duct_hierarchy.edn resources?

weavejester avatar Nov 19 '19 00:11 weavejester

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?

0x4d6165 avatar Nov 19 '19 02:11 0x4d6165

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.

weavejester avatar Nov 19 '19 14:11 weavejester

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

0x4d6165 avatar Nov 26 '19 10:11 0x4d6165

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!

weavejester avatar Nov 26 '19 14:11 weavejester

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.

weavejester avatar Nov 26 '19 14:11 weavejester

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

0x4d6165 avatar Dec 02 '19 17:12 0x4d6165

You probably need to require the namespace for into-merger first...

weavejester avatar Dec 02 '19 20:12 weavejester

Hmm I can't find what package it's in..

0x4d6165 avatar Dec 02 '19 20:12 0x4d6165

It's in the boot.pod namespace. You can just search for the function on Github.

weavejester avatar Dec 02 '19 20:12 weavejester

Oh sweet I didn't know that! Thanks!

0x4d6165 avatar Dec 03 '19 01:12 0x4d6165