Схема, причиняваща неуспешно изграждане на uberimage

Разработвам просто уеб приложение hello world в Clojure. Въпреки това, след като добавих библиотеката Schema към моя проект, започнах да получавам грешката по-долу, когато се опитвах да създам uberjar с помощта на lein uberjar. Странно, но приложението все още преминава тестовете на модула и работи без грешки, когато стартира с lein dev.

По-долу е изходният файл, където използвам схема. За краткост съм пропуснал останалите си изходни файлове, но ако някой иска да види останалите, просто попитайте.

Вече се опитах да деактивирам AOT компилацията, тъй като това изглежда е основната разлика между нормалната компилация и изграждането на uberjar, но без зарове. Също така потърсих ключа „missing-required-key“ в изходния код на Schema и се уверих, че е цитиран правилно, определено изглежда така, тъй като ако го променя, тестовете на Schema започват да се провалят.

(ns server.api
  (:require [aleph.http :as http]
            [compojure.api.sweet :refer :all]
            [compojure.route :as route]
            [com.stuartsierra.component :as component]
            [ring.middleware.reload :refer [wrap-reload]]
            [ring.util.http-response :refer :all]
            [schema.core :as s]
            [server.logging :refer [wrap-exception-logging wrap-request-logging] :as log]))

(s/defschema Greeting
  {:hello s/Str
   s/Keyword s/Any})

(defn app [db]
  (api
   {:format {:formats [:json-kw]}}
   (middlewares [wrap-request-logging
                 wrap-exception-logging]
                (swagger-ui "/docs" :swagger-docs "/endpoints")
                (swagger-docs "/endpoints"
                 {:info {:title "Hello World Api"}})

                (GET* "/greet" []
                      :summary "Greets someone by name."
                      :description "Greets a person by name, telling them about
                                    the database configuration we're using as well."
                      :return Greeting
                      :query-params [name :- s/Str]
                      (ok {:hello name :with-db db}))

                (route/not-found (not-found {:error "Page not found."})))))

(defrecord Api
  [port env db logger]
  component/Lifecycle

  (start [{:keys [connection] :as component}]
    (if connection
      component
      (do (log/info "Starting Api at port" port "with env" env)
          (let [application (app db)
                handler (if (= env :dev) (wrap-reload application) application)
                conn (http/start-server handler {:port port :join? false})]
            (assoc component :connection conn)))))

  (stop [{:keys [connection] :as component}]
    (if-not connection
      component
      (do (log/info "Stopping Api")
          (.close connection)
          (assoc component :connection nil)))))

(defn new-api [port env]
  (->Api port env nil nil))

Какво друго е различно в процеса на компилиране при създаване на uberjar в сравнение с нормалното компилиране? Има ли нещо друго, което мога да опитам?

Основната причина е, че на lein uberjar-маршрута е даден невалиден вход (не е даден lein dev, вижте https://github.com/metosin/ring-swagger/blob/master/src/ring/swagger/swagger2_schema.clj#L13). Когато се добави, работи според очакванията.


person CalumMcCall    schedule 19.06.2015    source източник


Отговори (4)


Все пак даденото изключение беше наистина лошо и сега е коригирано в най-новия SNAPSHOT - използва стойности по подразбиране за липсващи полета и по този начин не прави проверка на схемата по време на компилиране за него.

Също така бих препоръчал да не се AOT цялото приложение. Вижте https://github.com/metosin/compojure-api/issues/129

Не съм виждал тази грешка преди (и ние внедряваме всички наши услуги със схема и uberjar). Изглежда, че ред 21 е междинният софтуер на swagger-docs; можете ли да опитате да го премахнете и да видите дали това решава проблема?

person Tommi Reiman    schedule 23.06.2015

Реагирах, че използвате _1_, за предпочитане е да използвате _2_. Това вероятно не е грешката тук, но прави кода много по-лесен за гмуркане за някой, който не знае толкова много за библиотеките.

person Jason Wolfe    schedule 19.06.2015
comment
Колкото повече разглеждам _1_, толкова по-малко разбирам как оценява своята таблица с маршрути и отстраняването на грешки в това трябва да е кошмар. Всъщност бих препоръчал да използвате друга, по-явна библиотека, за да улесните Swagger. - person CalumMcCall; 22.06.2015

Погледнах в compojure.api.sweet-именното пространство и виждам, че Zach Tellmans Potemkin се използва за „импортиране“ на всички функции от различни пространства от имена във вашето пространство от имена service.api. Може би това създава проблеми при създаването на буркан.

Бихте ли опитали да изискате swagger-ui и swagger-docs от тяхното оригинално пространство от имена, като добавите този ред към изискването?

Ако това не работи, но поне даде друго съобщение за грешка (може би), опитайте да require всички други символи, използвани изрично.

[compojure.api.swagger swagger-ui swagger-docs]

Не съм сигурен дали това ще помогне, но опитайте да стартирате :refer :all и вижте какви са преходните зависимости. Възможно е множество библиотеки да зависят от различни, несъвместими версии на една и съща зависимост. Сблъсквал съм се с това и преди, но нямам представа защо би се случило само когато е опаковано в uberjar.

person claj    schedule 19.06.2015
comment
Благодаря за подробния отговор. Опитах вашите предложения, като изрично посочих всичко, но все още получавам същото съобщение за грешка. Така че вероятно проблемът тук е нещо като конфликти в пространството на имена между различни библиотеки, които използвам? - person claj; 19.06.2015
comment
Мисля, че има някакъв конфликт в двата вложени макроса. Може би _1_ и вижте дали получените изрази се компилират... - person CalumMcCall; 22.06.2015
comment
java.lang.RuntimeException: Не може да се разреши символ: липсващ-необходим-ключ в този контекст, компилиране:(server/api.clj:21:17) в clojure.lang.Compiler.analyze(Compiler.java:6464) в clojure .lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$VectorExpr.parse(Compiler.java:3126) в clojure.lang.Compiler.analyze(Compiler.java:6447) в clojure.lang. Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$MapExpr.parse(Compiler.java:2981) в clojure.lang.Compiler.analyze(Compiler.java:6453) в clojure.lang.Compiler.analyze (Compiler.java:6406) в clojure.lang.Compiler$MapExpr.parse(Compiler.java:2981) в clojure.lang.Compiler.analyze(Compiler.java:6453) в clojure.lang.Compiler.analyze(Compiler. java:6406) в clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6646) в clojure.lang.Compiler.analyze(Compiler.java:6445 ) в clojure.lang.Compiler.access$100(Compiler.java:38) в clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:6050) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6644 ) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6632) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang .Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6646) в clojure.lang.Compiler. анализира (Compiler.java:6445) в clojure.lang.Compiler.analyze (Compiler.java:6406) в clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782) в clojure.lang.Compiler$LetExpr $Parser.parse(Compiler.java:6100) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6644) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyzeSeq( Compiler.java:6632) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$BodyExpr$Parser.parse(Компилатор .java:5782) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6644) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782) в clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:6100) в clojure.lang. Compiler.analyzeSeq(Compiler.java:6644) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6632) в clojure.lang.Compiler.analyze(Компилатор .java:6445) в clojure.lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782) в clojure.lang.Compiler$LetExpr$Parser. parse(Compiler.java:6100) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6644) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyzeSeq(Compiler.java :6632) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6632) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure .lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782) в clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:6100 ) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6644) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6632) в clojure.lang .Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6632) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyze( Compiler.java:6406) в clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782) в clojure.lang.Compiler$FnMethod.parse(Compiler.java:5217) в clojure.lang.Compiler$FnExpr .parse(Compiler.java:3846) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6642) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyzeSeq(Компилатор. java:6632) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719 ) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6646) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6632) в clojure.lang .Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6632) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyze( Compiler.java:6406) в clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6646) в clojure.lang. Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6632) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyze(Компилатор .java:6406) в clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6646) в clojure.lang.Compiler.analyze(Compiler.java: 6445) в clojure.lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6646) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719) в clojure.lang .Compiler.analyzeSeq(Compiler.java:6646) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6632) в clojure.lang.Compiler.analyze( Compiler.java:6445) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6632) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyze(Compiler.java:6406 ) в clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6646) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure .lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6646) в clojure.lang. Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6632) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyze(Компилатор .java:6406) в clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6646) в clojure.lang.Compiler.analyze(Compiler.java: 6445) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6632) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyze(Compiler.java:6406) в clojure. lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782) в clojure.lang.Compiler$FnMethod.parse(Compiler.java:5217) в clojure.lang.Compiler$FnExpr.parse(Compiler.java:3846) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6642) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang. Compiler.analyzeSeq(Compiler.java:6632) на clojure.lang.Compiler.analyze(Compiler.java:6445) на clojure.lang.Compiler.access$100(Compiler.java:38) на clojure.lang.Compiler$DefExpr$ Parser.parse(Compiler.java:538) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6644) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyze(Компилатор .java:6406) в clojure.lang.Compiler.compile1(Compiler.java:7221) в clojure.lang.Compiler.compile(Compiler.java:7292) в clojure.lang.RT.compile(RT.java:398) в clojure.lang.RT.load(RT.java:438) в clojure.lang.RT.load(RT.java:411) в clojure.core$load$fn__5066.invoke(core.clj:5641) в clojure. core$load.doInvoke(core.clj:5640) в clojure.lang.RestFn.invoke(RestFn.java:408) в clojure.core$load_one.invoke(core.clj:5446) в clojure.core$compile$fn__5071 .invoke(core.clj:5652) в clojure.core$compile.invoke(core.clj:5651) в user$eval9$fn__16.invoke(form-init1857067608391167398.clj:1) в user$eval9.invoke(form- init1857067608391167398.clj:1) в clojure.lang.Compiler.eval(Compiler.java:6703) в clojure.lang.Compiler.eval(Compiler.java:6693) в clojure.lang.Compiler.load(Compiler.java:7130 ) в clojure.lang.Compiler.loadFile(Compiler.java:7086) в clojure.main$load_script.invoke(main.clj:274) в clojure.main$init_opt.invoke(main.clj:279) в clojure.main $initialize.invoke(main.clj:307) в clojure.main$null_opt.invoke(main.clj:342) в clojure.main$main.doInvoke(main.clj:420) в clojure.lang.RestFn.invoke( RestFn.java:421) в clojure.lang.Var.invoke(Var.java:383) в clojure.lang.AFn.applyToHelper(AFn.java:156) в clojure.lang.Var.applyTo(Var.java:700 ) в clojure.main.main(main.java:37) Причинено от: java.lang.RuntimeException: Не може да се разреши символ: missing-required-key в този контекст в clojure.lang.Util.runtimeException(Util.java:221 ) в clojure.lang.Compiler.resolveIn(Compiler.java:6940) в clojure.lang.Compiler.resolve(Compiler.java:6884) в clojure.lang.Compiler.analyzeSymbol(Compiler.java:6845) в clojure.lang .Compiler.analyze(Compiler.java:6427) ... Още 153 изключения в нишката "main" java.lang.RuntimeException: Не може да се разреши символ: липсващ-задължителен-ключ в този контекст, компилиране:(server/api.clj :21:17) в clojure.lang.Compiler.analyze(Compiler.java:6464) в clojure.lang.Compiler.analyze(Compiler.java:6406) в clojure.lang. Compiler$VectorExpr.parse(Compiler.java:3126) в clojure.lang.Compiler.analyze(Compiler.java:6447) в clojure.lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$MapExpr .parse(Compiler.java:2981) в clojure.lang.Compiler.analyze(Compiler.java:6453) в clojure.lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$MapExpr.parse( Compiler.java:2981) в clojure.lang.Compiler.analyze(Compiler.java:6453) в clojure.lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$InvokeExpr.parse(Compiler.java :3719) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6646) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.access$100(Compiler.java:38) в clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:6050) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6644) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure .lang.Compiler.analyzeSeq(Compiler.java:6632) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$ InvokeExpr.parse(Compiler.java:3719) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6646) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyze(Компилатор .java:6406) в clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782) в clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:6100) в clojure.lang.Compiler. analysisSeq(Compiler.java:6644) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6632) в clojure.lang.Compiler.analyze(Compiler.java :6445) в clojure.lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782) в clojure.lang.Compiler.analyzeSeq(Compiler.java: 6644) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782 ) в clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:6100) в clojure.lang.Compiler.analyzeSeq(Compiler.java:6632) в clojure.lang.Compiler.analyze(Compiler.java:6445) на clojure.lang.Compiler.access$100(Compiler.java:38) на clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:538) на clojure.lang. Compiler.analyzeSeq(Compiler.java:6644) в clojure.lang.Compiler.analyze(Compiler.java:6445) в clojure.lang.Compiler.analyze(Compiler.java:6406) в clojure.lang.Compiler.compile1(Компилатор .java:7221) в clojure.lang.Compiler.compile(Compiler.java:7292) в clojure.lang.RT.compile(RT.java:398) в clojure.lang.RT.load(RT.java:438) в clojure.lang.RT.load(RT.java:411) в clojure.core$load$fn__5066.invoke(core.clj:5641) в clojure.core$load.doInvoke(core.clj:5640) в clojure. lang.RestFn.invoke(RestFn.java:408) в clojure.core$load_one.invoke(core.clj:5446) в clojure.core$compile$fn__5071.invoke(core.clj:5652) в clojure.core$compile .invoke(core.clj:5651) при user$eval9$fn__16.invoke(form-init1857067608391167398.clj:1) при user$eval9.invoke(form-init1857067608391167398.clj:1) при clojure.lang.Compiler.eval( Compiler.java:6703) в clojure.lang.Compiler.eval(Compiler.java:6693) в clojure.lang.Compiler.load(Compiler.java:7130) в clojure.lang.Compiler.loadFile(Compiler.java:7086 ) в clojure.main$load_script.invoke(main.clj:274) в clojure.main$init_opt.invoke(main.clj:279) в clojure.main$initialize.invoke(main.clj:307) в clojure.main $null_opt.invoke(main.clj:342) в clojure.main$main.doInvoke(main.clj:420) в clojure.lang.RestFn.invoke(RestFn.java:421) в clojure.lang.Var.invoke( Var.java:383) в clojure.lang.AFn.applyToHelper(AFn.java:156) в clojure.lang.Var.applyTo(Var.java:700) в clojure.main.main(main.java:37) Причинено от: java.lang.RuntimeException: Не може да се разреши символ: липсващ-необходим-ключ в този контекст на clojure.lang.Util.runtimeException(Util.java:221) на clojure.lang.Compiler.resolveIn(Compiler.java:6940 ) в clojure.lang.Compiler.resolve(Compiler.java:6884) в clojure.lang.Compiler.analyzeSymbol(Compiler.java:6845) в clojure.lang.Compiler.analyze(Compiler.java:6427) ... 153 повече Неуспешна компилация: Неуспешен подпроцес - person claj; 22.06.2015

Благодаря за бакшиша! Премахването на ред 21/22 наистина реши проблема. Сега трябва да разбера защо самонадеяността го кара да се провали... Какво ви накара да подозирате, че това е проблемът?

person CraigM    schedule 22.06.2015