2017-02-21 21 views
21

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

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

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

Чтобы обойти это, я прочитал, что I need to create Automatic Modules. Из того, что я понимаю, мне нужно переименовать банки rxjava и rxjavafx, чтобы иметь простое имя, а затем перечислить банки в параметре --module-path. Затем я добавляю директиву requires в своем module-info.java с названиями баннеров.

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

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

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) 
+2

Небольшие улучшения (возможно): при извлечении имени модуля из JAR-имени система модулей выкинет подстроки, похожие на версии ~> попробуйте, не переименовав их. Путь к модулю также принимает каталоги ~> в случае, если у вас есть каталог, который содержит только зависимости, поместите его прямо в путь модуля. – Nicolai

+2

Не связанный с вашим текущим вопросом, я предлагаю перейти на новую сборку JDK 9. Build 148 (я думаю) внес существенные изменения в доступность частных типов и членов через отражение. Текущая сборка - 157. –

ответ

14

Am I using the new module system correctly?

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

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

Например:
com.foo.A (от moduleA.jar)
com.foo.B (от moduleB.баночка)

What can I do about this error?

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

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

Do these dependencies prevent me from updating, or should I just wait for rx to update their libs?

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

+1

Хм, это немного разочаровывает. Думаю, было бы нелегко написать задачу градиента для объединения разделенных пакетов. Однако нужно быть умным. Не хотите разрушать время сборки, повторно упаковывая чужие библиотеки ¯ \\ _ (ツ) _/¯ – flakes

+4

Да, это боль, но afaik есть преимущества безопасности + производительности, чтобы запретить разделенные пакеты. Надеемся, что владельцы lib будут быстро предлагать комбинированные баночки. Или я мог видеть центральный центр, обеспечивающий автоматические комбинированные банки. –

+1

Смешно читать java 9 заметок о миграции, что jdk9 вряд ли нарушит ваш код. Но это ограничение ломает тонны библиотек. Разделенные пакеты - очень распространенная практика для библиотек, которые распространяются через несколько банок. – eugcomax

3

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

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 зависимости» или «МВН зависимость: дерево» может быть полезным) и исключая по код simmiliar для:

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

+0

У меня такая же проблема, но в этом случае исключение из-за зависимостей 'boss-transaction-api_1.2_spec' не получилось. Он содержит дополнительные классы в пакете 'java.transaction.xa', которые не находятся в одном пакете, экспортированном модулем' java.sql'. Следовательно, вместо этого я получаю исключения вместо java.lang.ClassNotFoundException. Мне, возможно, придется «unmodularise» мой проект, пока это не будет разрешено. – Paul