2017-02-21 68 views
21

Z Java 9 na zbliżającym się horyzoncie myślałem, że byłoby dobrym ćwiczeniem edukacyjnym do przeniesienia niektórych moich projektów na Java 9. W jednym z moich projektów mam zależności od rxjava i rxjavafxKonflikty w pakietach z automatycznymi modułami w Javie 9

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

Chcę utworzyć ten projekt jako nazwany moduł. Aby to zrobić, muszę utworzyć plik module-info.java i muszę tutaj określić wymagania dla rxjava i rxjavafx. Jednak te biblioteki nie mają jeszcze żadnych informacji o module.

Aby obejść ten problem, przeczytałem: I need to create Automatic Modules. Z tego co rozumiem, muszę zmienić nazwę słoików rxjava i rxjavafx, aby mieć prostą nazwę, a następnie listę słoików w parametrze --module-path. Następnie dodam dyrektywę requires w moim module-info.java z nazwami słoików.

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

Napisałem zadanie gradle, aby edytować nazwy słoików dla mnie i wygląda na to, że działa w większości przypadków. Zajmuje wszystkie słoiki, które należy skompilować i zmienia ich nazwy tak, aby nie zawierały informacji o wersji ani ukośników. Pliki te są następnie łączone w : oddzielone wyrażenie:

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(':')] 
} 

Naturalnie biblioteki rx dzielić niektóre z ich nazw pakietów ... to jednak powoduje, że kompilator pluć powrotem błędy, takie jak:

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 

Wygląda na to, że jedynym sposobem obejścia tego problemu byłoby ponowne spakowanie zawartości rxjava i rxjavafx do pojedynczego słoika i dodanie go jako pojedynczego modułu. To nie wydaje się dobrym rozwiązaniem mimo ...

Więc moje pytania to:

  • Am I poprawnie przy użyciu nowego systemu modułu?
  • Co mogę zrobić z tym błędem? i
  • Czy te zależności uniemożliwiają mi aktualizację, czy powinienem poczekać, aż rx zaktualizuje swoje biblioteki?

Uwaga: Próbowałem ten działa ze standardowym java/javac i powodują te same problemy. Również tutaj jest moja wersja 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

Małe ulepszenia (możliwe): Podczas wyodrębniania nazwy modułu z nazwy JAR, system modułowy będzie wydzielał podciągi, które wyglądają jak wersje ~> wypróbuj bez zmiany ich nazwy. Ścieżka modułu również akceptuje katalogi ~> w przypadku, gdy masz katalog zawierający tylko zależności, umieść go bezpośrednio na ścieżce modułu. – Nicolai

+2

Niezwiązane z twoim bieżącym pytaniem, proponuję uaktualnienie do nowszej wersji JDK 9. Zbudowanie 148 (jak sądzę) wprowadziło kilka istotnych zmian w dostępności prywatnych typów i członków za pomocą refleksji. Obecna wersja to 157. –

Odpowiedz

14

Am I using the new module system correctly?

Tak. To, co widzisz, to zamierzone zachowanie, a to dlatego, że moduły JPMS nie zezwalają na dzielenie pakietów.

Jeśli nie znasz terminu "podzielone paczki", oznacza to zasadniczo dwóch członków tego samego pakietu pochodzących z dwóch różnych modułów.

Na przykład:
com.foo.A (od moduleA.jar)
com.foo.B (z moduleB.jar)

What can I do about this error?

Masz dwie opcje:

  1. (twardsza) "nierozszczepionych" zależności pakietów. Jednak może to być trudne lub niemożliwe, jeśli nie jesteś zaznajomiony z wewnętrznym działaniem biblioteki (łatwiej) połączyć dwa słoiki w pojedynczy słoik (a zatem pojedynczy moduł automatyczny), jak wspomniano powyżej. Zgadzam się, że nie jest to "dobre" rozwiązanie, ale przede wszystkim podzielenie pakietów nie jest dobrym pomysłem.

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

Mam nadzieję RX ostatecznie aktualizować ich libs nie zostały podzielone na pakiety, w pewnym momencie w przyszłości. Do tego czasu moim zaleceniem byłoby rozbicie dwóch słoików w jeden słoik (opcja nr 2).

+1

Hmm, to trochę rozczarowujące. Sądzę, że nie byłoby zbyt trudno napisać zadanie gradle do łączenia dzielonych pakietów. Musi być jednak sprytny. Nie chcę niszczyć mojego czasu kompilacji, przepakowując czyjś bibliotekę ¯ \\ _ (ツ) _/¯ – flakes

+4

Tak, to jest ból, ale jest pewne korzyści z bezpieczeństwa i wydajności, które uniemożliwiają dzielenie pakietów. Mam nadzieję, że właściciele lib będą szybko dostarczać połączone słoiki. Albo widziałem maven central zapewniający automatyczne łączenie słoików. –

+1

Zabawne jest, że podczas czytania migracji do java 9 zauważyliśmy, że jdk9 bardzo nie złamie kodu. Ale to ograniczenie łamie ton bibliotek. Rozdzielone pakiety są bardzo powszechną praktyką w przypadku bibliotek dystrybuowanych za pośrednictwem kilku słoików. – eugcomax

3

miałem simmiliar problem:

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 

mogę pozbyć się problemu rozdzielne pakiety kompilacji sprawdzając mój projekt przechodnia zależnościami („Gradle zależności” lub „mvn Zależność: drzewo” może być pomocne) i wyłączeniem przez Kod simmiliar do:

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

lub

<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> 

Nie słoik rep Potrzebowałem pomocy w moim problemie. Ten problem nie wystąpił w # JDK8. Prawdopodobnie wyłączenie zależności nie pomaga w każdym projekcie.

+0

Mam dokładnie ten sam problem, ale w tym przypadku nie działa zależność 'boss-transaction-api_1.2_spec'. Zawiera dodatkowe klasy w pakiecie 'java.transaction.xa', które nie znajdują się w tym samym pakiecie wyeksportowanym przez moduł' java.sql'. W związku z tym otrzymuję wyjątki środowiska wykonawczego 'java.lang.ClassNotFoundException'. Być może będę musiał "unmodularise" mój projekt, dopóki to nie zostanie rozwiązane. – Paul