Ошибка NoClassDefFoundError во время выполнения приложения, созданного с помощью sbt

#scala #jar #sbt #sbt-native-packager

#scala #jar #sbt #sbt-native-packager

Вопрос:

У меня есть следующий файл build.sbt:

 lazy val shared = (project in file("shared")) .
  settings (moduleName := "x-shared") .
  ...

lazy val service = (project in file ("service")) .
  settings (moduleName := "x-api") .
  dependsOn (shared % "compile->compile;test->test", job % "compile->compile;test->test") .
  aggregate (shared, joob) .
  ...

lazy val job = (project in file("job") dependsOn (shared % "compile->compile;test->test")) .
  settings (moduleName := "x-job") .
  ...
  

Подмодуль service требует как общих, так и рабочих модулей. Общий проект — это, по сути, набор классов, используемых всеми модулями. И задание, и служба — это разные приложения, но у нас есть конечная точка в службе, которая требуется для запуска приложения задания.

Проблема в том, что во время выполнения мы получаем следующую ошибку при попытке ссылаться на классы модуля задания:

 java.lang.NoClassDefFoundError: com/earnest/ingestor/models/Pipeline$
  

Но мы можем ссылаться на общий модуль без каких-либо проблем.

Структура папок проекта следующая:

 ./root
  ./service
  ./shared
  ./job
  

Одна вещь, которую я замечаю, это то, что файл jar, созданный для модуля задания, не копируется в папки lib в сервисном модуле, в отличие от общего файла jar:

каталог service / target / universal / stage / lib содержит оба:

 com.earnest.x-api-localdev.9288.jar
com.earnest.x-shared-localdev.9288.jar
  

Но jar-файл задания заполняется в модуле jobs:

задание / цель / универсальный / этап / библиотека содержит:

 com.earnest.x-job-localdev.9288.jar
  

Я довольно новичок в сборках sbt, поэтому не уверен, может ли отсутствовать какая-то часть во время сборки, которая выполняется с помощью команды sbt clean . Мы используем плагин sbt-native-package. Я не уверен, какая другая информация может быть полезной для обмена, поэтому я извлек ключевые моменты build.sbt, заранее спасибо за помощь.

плагины sbt:

 addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.9.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.11")
  

Обновление 1

Приложение запускается из launcher.jar используя то, что кажется LauncherJarPlugin из файла build.sbt. Одна вещь, которую я заметил, это то, что launcher.jar не содержит com.earnest.x-job-localdev.9288.jar в пути к классу на META_INF/MANIFEST.MF

Комментарии:

1. Какую команду сборки вы использовали? sbt-native-packager обычно не используется для создания uberjar. Для этого sbt-assembly обычно используется.

2. Я использую sbt clean <module> команду, не уверен, как она настраивается, но эта команда создает полный проект. Еще одна вещь, которую я заметил, это то, что приложение запускается через launcher.jar , Я вижу, что мы также используем LauncherJarPlugin в build.sbt, который, если он извлечен с помощью jar xf команды, META_INF/MANIFEST.MF не включается com.earnest.x-job-localdev.9288.jar в путь к классу.

3. Без подробностей о конфигурации я сомневаюсь, что мы сможем разобраться в этом.

4. Должен ли я делиться только полным файлом build.sbt? Я просто не хотел копировать вставлять весь этот блок.

5. Скопируйте и вставьте все, что связано с логикой построения.

Ответ №1:

Я смог решить свою проблему с настройкой добавления сервисного модуля job % "compile->compile;test->test"

Весь блок выглядит так:

 lazy val service = (project in file ("service")) .
  settings (moduleName := "x-api") .
  dependsOn (shared % "compile->compile;test->test", job % "compile->compile;runtime->runtime;test->test") .
  aggregate (shared, job) .
  ...