Есть ли способ добавить maven-зависимости при использовании maven-jlink-plugin?

Я использую этот проект Github, чтобы познакомиться с новыми модульными функциями в Java 9. Я хотел бы добавить зависимости в проект и иметь возможность создавать собственный образ. Однако, когда я пытаюсь добавить новую зависимость в pom.xml и добавить инструкцию require в module-info.java, я получаю следующую ошибку из maven-jlink-plugin:

Error: module-info.class not found for joda.time module

Я пытаюсь использовать это как подтверждение концепции, что я могу развернуть образы, используя новую фазу связывания, но, естественно, мне нужно иметь возможность иметь внешние зависимости и мне нужно использовать maven (ограничение работы).

Изменения в mod-jar/pom.xml

...
 <dependencies>
    <dependency>
      <groupId>joda-time</groupId>
      <artifactId>joda-time</artifactId>
      <version>2.9.9</version>
    </dependency>
  </dependencies>
...

мод-банка /module-info.java

module com.soebes.nine.jar {
  requires java.base;
  requires joda.time;
  exports com.soebes.example.nine.jar;
}

Журналы:

[INFO] --- maven-jlink-plugin:3.0.0-alpha-1:jlink (default-jlink) @ mod-jlink ---
[INFO] Toolchain in maven-jlink-plugin: jlink [ /Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/jlink ]
[INFO] The following dependencies will be linked into the runtime image:
[INFO]  -> module: com.soebes.nine.one ( /Users/sebastianrestrepo/Projects/jdk9-jlink-jmod-example/maven-example/mod-1/target/jmods/com.soebes.nine.one.jmod )
[INFO]  -> module: com.soebes.nine.two ( /Users/sebastianrestrepo/Projects/jdk9-jlink-jmod-example/maven-example/mod-2/target/jmods/com.soebes.nine.two.jmod )
[INFO]  -> module: com.soebes.nine.jar ( /Users/sebastianrestrepo/Projects/jdk9-jlink-jmod-example/maven-example/mod-jar/target/com.soebes.nine.jar-1.0-SNAPSHOT.jar )
[INFO]  -> module: joda.time ( /Users/sebastianrestrepo/.m2/repository/joda-time/joda-time/2.9.9/joda-time-2.9.9.jar )
[ERROR] 
Error: module-info.class not found for joda.time module
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] parent ............................................. SUCCESS [  1.460 s]
[INFO] com.soebes.nine.one ................................ SUCCESS [  2.022 s]
[INFO] com.soebes.nine.two ................................ SUCCESS [  1.392 s]
[INFO] com.soebes.nine.jar ................................ SUCCESS [  1.388 s]
[INFO] mod-jlink .......................................... FAILURE [  1.061 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.911 s
[INFO] Finished at: 2017-11-03T15:27:35-04:00
[INFO] Final Memory: 26M/981M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-jlink-plugin:3.0.0-alpha-1:jlink (default-jlink) on project mod-jlink: 

Я был бы очень признателен за любую помощь. Благодарю.

4 ответа

Решение

Это не имеет ничего общего с плагином, я верю. модуль joda.time в твоем случае кажется автоматическим модулем.

jlink Инструмент не поддерживает связывание автоматических модулей, потому что они могут полагаться на произвольное содержимое пути к классам, что противоречит идее автономной среды выполнения Java.

Таким образом, есть два способа исправить это: -

  • (у вас нет баночки) Временно создайте module-info.java [Вы могли бы использовать jdeps инструмент для него] и обновить банку [используя jar tool] с соответствующим скомпилированным классом, как в проектах под Java 9.

  • (у вас есть зависимость) Постоянно переносите jar в Java 9, где он будет состоять из module-info.class сам по себе после компиляции и упаковки.

Вы можете использовать плагин ModiTect Maven, чтобы добавить дескриптор модуля в JAR и создать модульный образ среды выполнения с этим модулем.

Отказ от ответственности: я автор ModiTect.

У меня была похожая проблема в одном из моих проектов. Сначала я попробовал moditect-maven-plugin, которая отлично сработала! Однако с помощью этого плагина вам необходимо отдельно настроить каждую зависимость, в которой отсутствует дескриптор модуля. Если у вас есть много зависимостей, в которых отсутствует дескриптор модуля, это может стать громоздким.

Поэтому я решил разработать новый плагин maven, jigsaw-maven-plugin(см. ). Плагин обеспечивает три цели: исправление всех безымянных модулей (см. Шаг 3), а также связывание и упаковку этих модулей (см. Шаги 4 и 5) .

Перед установкой исправлений, компоновкой и упаковкой вам необходимо собрать проект JAR (см. Шаг 1) и скопировать зависимости проекта (см. Шаг 2) в общее место (например, ${project.build.directory}/modules). Возможно, вы можете использовать следующие конфигурации плагинов сборки, чтобы начать работу (подробнее см. На https://github.com/ghackenberg/jigsaw-maven-pluginстранице GitHub ):

Шаг 1. Создайте архив

      <plugin>
  <artifactId>maven-jar-plugin</artifactId>
  <version>3.2.0</version>
  <configuration>
    <outputDirectory>${project.build.directory}/modules</outputDirectory>
  </configuration>
</plugin>

Шаг 2. Скопируйте зависимости

      <plugin>
  <artifactId>maven-dependency-plugin</artifactId>
  <version>3.2.0</version>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>copy-dependencies</goal>
      </goals>
      <configuration>
        <outputDirectory>${project.build.directory}/modules</outputDirectory> 
      </configuration>
    </execution>
  </executions>
</plugin>

Шаг 3. Исправьте все неназванные модули

Искать JAR в modulePath отсутствует дескриптор модуля, сгенерируйте недостающие дескрипторы модуля, используя jdeps а также javac, и добавьте их в соответствующие JAR-файлы, используя java.util.zip.

      <plugin>
  <groupId>io.github.ghackenberg</groupId>
  <artifactId>jigsaw-maven-plugin</artifactId>
  <version>1.0.0</version>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>patch</goal>
      </goals>
      <configuration>
        <modulePath>${project.build.directory}/modules</modulePath>
      </configuration>
    </execution>
  </executions>
</plugin>

Шаг 4. Свяжите модули

Свяжите модули с помощью jlink.

      <plugin>
  <groupId>io.github.ghackenberg</groupId>
  <artifactId>jigsaw-maven-plugin</artifactId>
  <version>1.0.0</version>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>link</goal>
      </goals>
      <configuration>
        <modulePath>${project.build.directory}/modules</modulePath>
        <module>your.module.name</module>
        <output>${project.build.directory}/image</output>
      </configuration>
    </execution>
  </executions>
</plugin>

Шаг 5: Модули пакета

Модули пакета, использующие jpackage.

      <plugin>
  <groupId>io.github.ghackenberg</groupId>
  <artifactId>jigsaw-maven-plugin</artifactId>
  <version>1.0.0</version>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>package</goal>
      </goals>
      <configuration>
        <modulePath>${project.build.directory}/modules</modulePath>
        <runtimeImage>${project.build.directory}/image</runtimeImage>
        <mainClass>your.module.name/your.package.Main</mainClass>
      </configuration>
    </execution>
  </executions>
</plugin>

Позвольте мне попытаться объяснить технические основы этого:

joda-time в версии 2.9.9, как указано в вопросе, является немодулярным jar-файлом, он не содержит module-info.class и не объявляет себя автоматическим модулем с использованием Automatic-Module-Name: in его META-INF/MANIFEST.MF

Классы в реальном модуле не могут вызывать классы на пути к классам, поэтому вы не можете использовать "require jode.time" в вашем модуле-info с этой версией.

Автоматические модули могут использовать классы на ClassPath. Чтобы использовать классы из немодульного фляги в реальном модуле, вы можете использовать обертку, которая сама является автоматическим модулем.

К настоящему времени существует версия 2.10.1 joda-time, которая является автоматическим модулем и объявляет "Automatic-Module-Name: org.joda.time", таким образом, вы можете использовать "require org.joda.time" в своем настоящий модуль с этой новой версией.

Теперь новый инструмент jlink не может работать напрямую с немодулярными банками или автоматическими банками, и плагин maven-jlink в настоящее время является просто оболочкой maven вокруг инструмента jlink, переводя свои параметры конфигурации в аргументы для инструмента jlink.

Чтобы создать пользовательскую среду выполнения Java для проектов, использующих смешанные зависимости maven с реальными модулями, автоматическими модулями и немодульными банками, вы должны знать все зависимости системных модулей ваших реальных модулей, автоматических модулей и немодульных банок и использовать их. параметр --add-modules, чтобы связать с ними.

Чтобы собрать зависимости системного модуля, вы можете использовать новый инструмент jdeps с параметром --print-module-deps или --list-deps в зависимости от используемой версии JDK.

Если вы используете maven для своего проекта, вы можете автоматизировать эту задачу, создав или используя плагин maven, который сделает это за вас.

Другие вопросы по тегам