随着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
的要求。但是,这些库还没有任何模块信息。
为了解决这个问题,我已经阅读了I need to create Automatic Modules。根据我的理解,我需要重命名rxjava
和rxjavafx
jar以获得一个简单的名称,然后在--module-path
参数中列出jar。然后,我在requires
中添加了module-info.java
指令,其中包含jar名称。
module com.foo.bar {
requires rxjavafx;
requires rxjava;
}
我编写了一个gradle任务来为我编辑jar名称,它似乎在大多数情况下都有效。它需要编译所有的jar并将它们重命名为不包含version-info或slashes。然后将这些文件连接成:
分隔的字符串:
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
的内容重新打包到一个jar中,并将其添加为单个模块。尽管......这似乎不是一个好的解决方案。
所以我的问题是:
注意:我已尝试使用标准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)
答案 0 :(得分:19)
我是否正确使用新模块系统?
是。您所看到的是预期的行为,这是因为JPMS模块不允许拆分包。
如果您不熟悉术语“拆分包”,它实质上意味着来自两个不同模块的同一包的两个成员。
例如:
com.foo.A(来自moduleA.jar)
com.foo.B(来自moduleB.jar)
我该怎么办这个错误?
您有两种选择:
这些依赖项是否会阻止我更新,还是应该等待rx更新它们的库?
希望rx最终会更新他们的库,以便在将来的某个时候没有拆分包。在那之前,我的建议是将两个罐子一起粉碎成一个罐子(选项#2)。
答案 1 :(得分:3)
我有类似的问题:
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依赖关系:树"可能会有所帮助)并且通过熟悉的代码排除:
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上没有出现此问题。可能排除依赖项对每个项目都没有帮助。
答案 2 :(得分:1)
我在从javaee和java.transaction.xa读取java.transaction.xa包时也遇到了相同的问题。 我通过将这一行添加到我的modul-info.java
中来修复它 opens javax.transaction.xa;
它工作正常,但显示提示,表明软件包javax.transaction.xa为空或不存在。但是源代码可以正确编译。