Flyway не может найти миграции в classpath, только если я запускаю приложение после его сборки с помощью jlink - PullRequest
0 голосов
/ 24 января 2020

Я использую Gradle's badass-jlink-plugin для сборки java, моего приложения JavaFX и его зависимостей в один артефакт - пользовательскую среду выполнения - так что я могу поделиться только zip файлом.

Я создал MWE для своей проблемы, которая доступна здесь: https://github.com/VictorAtPL/jlink_badass_flyway_classpath_problem

После выполнения prepareModulesDir задачи этого плагина, в build/jlinkbase/jlinkjars есть следующие jar s:

  1. jar s с зависимостями, которые были модульными (содержит module-info.class с начала; javafx-base-12.0.1-linux.jar, derby-10.15.1.3.jar, et c. ),
  2. зависимость для всех jar, которая содержит все файлы зависимостей, которые не были модульными (авторы не сделали их модульными, добавив, среди прочего, module-info.java file; jlink_badass_flyway_classpath_problem.merged.module-0.1.0-alpha.jar),
  3. jar с, которые являются прокси для файла универсального jar (с помощью предложения require transitive в module-info.java; flyway-core-6.1.4.jar),
  4. jar с классами и ресурсами основного модуля приложения (jlink_badass_flyway_classpath_problem-0.1.0-alpha.jar).

Подробнее о том, как работает badass-jlink-plugin, можно найти в документации здесь: https://badass-jlink-plugin.beryx.org/releases/latest/#_how_it_works

Основной модуль приложения содержит ресурсы (.sql файлы в src/main/resources/db/migration) и классы (.java файлы в src/main/java/db/migration), которые являются миграциями для Flyway библиотека.

Если я создаю пользовательские образы времени выполнения с помощью задачи jlink (сценарий ./jlink.sh) и запускаю приложение с использованием установленной системы java (run_system_java.sh, которая выполняет /usr/lib/jvm/java-11-oracle/bin/java --module-path /usr/lib/jvm/java-11-oracle/jmods/:./build/jlinkbase/jlinkjars --module jlink_badass_flyway_classpath_problem/app.Main), то Flyway работает правильно (находит и применяет обе миграции).

Если я запускаю приложение, используя пользовательскую среду выполнения (./run_assembled_java.sh, которая выполняет ./build/image/bin/java -m jlink_badass_flyway_classpath_problem/app.Main), я получил следующее предупреждение:

Jan 24, 2020 8:22:38 PM org.flywaydb.core.internal.scanner.classpath.ClassPathScanner findResourceNames
WARNING: Unable to resolve location classpath:db/migration

Таким образом, во время выполнения jlink с помощью badass-jlink-plugin что-то прерывается, потому что db/migration невозможно найти после создания файла modules для пользовательской среды выполнения.

Это команда, выполняемая jlink task:

/usr/lib/jvm/java-11-oracle/bin/jlink -v --compress 2 --no-header-files --no-man-pages --module-path /usr/lib/jvm/java-11-oracle/jmods/:/home/piotr/IdeaProjects/jlink_badass_flyway_classpath_problem/build/jlinkbase/jlinkjars --add-modules jlink_badass_flyway_classpath_problem --output /home/piotr/IdeaProjects/jlink_badass_flyway_classpath_problem/build/image

Я также прикрепляю результат gradle jlink и jimage list build/image/lib/modules: https://gist.github.com/VictorAtPL/69e50e1738429548d1e6d8070e37b062

Я думаю, что основная причина, почему он действует как это то, что эта строка в ClassPathScanner.java из Flyway действует по-разному при работе с h разные javas (устанавливаемые системой и настраиваемые среды выполнения, созданные jlink).

В первом сценарии он находит URL: jar:file:///home/piotr/IdeaProjects/jlink_badass_flyway_classpath_problem/build/jlinkbase/jlinkjars/jlink_badass_flyway_classpath_problem-0.1.0-alpha.jar!/db/migration/, во втором - нет (classLoader.getResources("db/migration").nextElement() throws java.util.NoSuchElementException ; но classLoader.getResources("db/migration/V1__Initial_version.sql").nextElement() работает).

Я предоставляю скриншоты для второго сценария (с пользовательским java временем выполнения): getResources on file getResources on directory

Я полагаю, что есть некоторая проблема с classLoader при работе с modules из java пользовательской среды выполнения. Почему я не могу искать каталоги при использовании jrt основанных URL-адресов?

Я был бы признателен, если бы кто-нибудь помог мне.

1 Ответ

1 голос
/ 28 января 2020

Не уверен, почему он ведет себя по-разному в этих двух сценариях ios, но ClassPathScanner от Flyway найдет ресурсы, если вы разместите их в пути к классам. Для этого вы можете скопировать ресурсы в подкаталог вашего изображения и добавить этот подкаталог в classpath:

tasks.jlink {
    doLast {
        copy {
            from 'src/main/resources'
            into "$imageDir/bin/data"
        }
    }
}

jlink {
    ...
    launcher {
        ...
        jvmArgs = ['-cp', '$DIR/data/']
    }
}

Я отправил вышеуказанные изменения как запрос на извлечение в ваш MWE: https://github.com/VictorAtPL/jlink_badass_flyway_classpath_problem/pull/1

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...