Пакет конфликтует с автоматическими модулями в 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)
Ответы
Ответ 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. Вероятно, исключение зависимостей не помогает в каждом проекте.