Подтвердить что ты не робот

Пакет конфликтует с автоматическими модулями в Java 9

С Java 9 на близком горизонте я подумал, что было бы хорошим упражнением по обучению переносить некоторые из моих проектов на Java 9. В одном из моих проектов у меня есть зависимости для rxjava и rxjavafx

dependencies {
    compile 'io.reactivex:rxjava:1.2.6'
    compile 'io.reactivex:rxjavafx:1.0.0'
    ...
}

Я хочу создать этот проект как именованный модуль. Для этого мне нужно создать файл module-info.java, и мне нужно указать требования для rxjava и rxjavafx здесь. Однако у этих библиотек еще нет информации о модуле.

Чтобы обойти это, я прочитал, что Мне нужно создать автоматические модули. Насколько я понимаю, мне нужно переименовать банки rxjava и rxjavafx, чтобы иметь простое имя, а затем перечислить банки в параметре --module-path. Затем я добавляю директиву requires в моем module-info.java с именами jar.

module com.foo.bar {
    requires rxjavafx;
    requires rxjava;
}

Я написал задачу gradle для редактирования имен jar для меня, и она работает в большинстве случаев. Он берет все банки, которые необходимо скомпилировать, и переименовывает их, чтобы не включать информацию о версии или слэши. Затем файлы конкатенируются в : разделенную строку:

tasks.withType(JavaCompile) {
    delete { delete '/tmp/gradle' }
    copy {
        from configurations.compile + configurations.testCompile
        into '/tmp/gradle'
        rename '(.*)-[0-9]+\\..*.jar', '$1.jar'
        rename { String fileName -> fileName.replace("-", "") }
    }
    options.compilerArgs += ['--module-path', fileTree(dir: '/tmp/gradle', include: '*.jar').getFiles().join(':')]
}

Естественно, библиотеки rx разделяют некоторые из их имен пакетов... это, однако, заставляет компилятор выплевывать обратно ошибки, такие как:

error: module  reads package rx.subscriptions from both rxjava and rxjavafx
error: module  reads package rx.schedulers from both rxjava and rxjavafx
error: module  reads package rx.observables from both rxjava and rxjavafx
error: module rxjava reads package rx.subscriptions from both rxjavafx and rxjava
error: module rxjava reads package rx.schedulers from both rxjavafx and rxjava
error: module rxjava reads package rx.observables from both rxjavafx and rxjava
error: module rxjavafx reads package rx.subscriptions from both rxjava and rxjavafx
error: module rxjavafx reads package rx.schedulers from both rxjava and rxjavafx
error: module rxjavafx reads package rx.observables from both rxjava and rxjavafx

Кажется, что единственный способ обойти эту проблему состоял в том, чтобы повторно упаковать содержимое rxjava и rxjavafx в одну банку и добавить это как один модуль. Это не похоже на хорошее решение, хотя...

Итак, мои вопросы:

  • Правильно ли я использую новую модульную систему?
  • Что я могу сделать с этой ошибкой? и
  • Могут ли эти зависимости мешать мне обновляться, или мне просто ждать, пока rx обновит их библиотеки?

Примечание. Я попытался запустить это со стандартным java/javac, и они вызывают те же проблемы. Также здесь моя версия java:

java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+140)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+140, mixed mode)
4b9b3361

Ответ 1

Я правильно использую новую систему модулей?

Да. То, что вы видите, - это предполагаемое поведение, и это связано с тем, что модули JPMS не разрешают разделенные пакеты.

Если вы не знакомы с термином "сплит-пакеты", это означает, что, по сути, два члена одного и того же пакета поступают из двух разных модулей.

Например:
com.foo.A(от модуляA.jar)
com.foo.B(from moduleB.jar)

Что я могу сделать с этой ошибкой?

У вас есть два варианта:

  • (сложнее) "нераспределяет" зависимости пакета. Однако это может быть сложно или невозможно, если вы не знакомы с внутренней работой библиотеки
  • (проще) объедините две банки в одну банку (и, следовательно, один автоматический модуль), как вы упомянули выше. Я согласен с тем, что это не "хорошее" решение, но, с разбивкой пакетов, в первую очередь, это тоже не очень хорошая идея.

Помогают ли эти зависимости предотвратить обновление, или я должен просто ждать, пока rx обновит их библиотеки?

Надеемся, что rx в конечном итоге обновит свои библиотеки, чтобы в какой-то момент в будущем не иметь разделенных пакетов. До тех пор моя рекомендация заключалась в том, чтобы просто разбить две банки вместе в одну банку (вариант № 2).

Ответ 2

У меня была знакомая проблема:

error: module flyway.core reads package javax.transaction.xa from both jboss.transaction.api.1.2.spec and java.sql
error: module slf4j.api reads package javax.transaction.xa from both jboss.transaction.api.1.2.spec and java.sql
error: module hibernate.core reads package javax.transaction.xa from both jboss.transaction.api.1.2.spec and java.sql
.../src/main/java/module-info.java:1: error: module eu.com.x reads package javax.transaction.xa from both java.sql and jboss.transaction.api.1.2.spec

Я мог бы избавиться от проблемы компиляции разделенных пакетов, проверив переходные зависимости проекта ( "gradle зависимостей" или "mvn dependency: tree" может быть полезно) и исключая код, похожий на:

configurations.all {
    exclude group: 'org.jboss.spec.javax.transaction', module: 'jboss-transaction-api_1.2_spec'
}

или

<dependencies>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>5.2.10.Final</version>
      <exclusions>
        <exclusion>
          <groupId>org.jboss.spec.javax.transaction</groupId>
          <artifactId>jboss-transaction-api_1.2_spec</artifactId>
        </exclusion>
      </exclusions> 
    </dependency>
  </dependencies>

В моей проблеме не было перекомпоновки контейнеров. Эта проблема не возникала на # JDK8. Вероятно, исключение зависимостей не помогает в каждом проекте.