Package 'com.example' reads package 'javafx.beans' from both 'javafx.base' and 'javafx.base'
Asked Answered
S

2

12

In module-info.java i get the error

Package 'com.example' reads package 'javafx.beans' from both 'javafx.base' and 'javafx.base'.

Not only does the migration (Java 8 to Java 11) frustrate me slowly but surely, this error does not make any sense to me.

The dependencies part fo my build.gradle:

def springFrameworkVersion = '5.1.2.RELEASE'
def hibernateVersion = '5.3.7.Final'
def junitJupiterVersion = '5.3.1'

dependencies {
  compile 'org.transentials:cardhouse-commons:1.1.1'
  compile 'ch.qos.logback:logback-classic:1.2.3'
  compile "org.springframework:spring-context:$springFrameworkVersion"
  compile "org.springframework:spring-jdbc:$springFrameworkVersion"
  compile "org.springframework:spring-orm:$springFrameworkVersion"
  compile "org.hibernate:hibernate-core:$hibernateVersion"
  compile 'org.apache.commons:commons-dbcp2:2.5.0'
  compile 'org.apache.commons:commons-lang3:3.8.1'
  compile 'commons-io:commons-io:2.6'
  compile 'com.h2database:h2:1.4.197'
  compile 'javax.xml.bind:jaxb-api:2.3.1'
  compile 'com.google.guava:guava:27.0-jre'
  compile 'org.flywaydb:flyway-core:5.2.1'
  compile 'javax.validation:validation-api:2.0.1.Final'
  compile "org.openjfx:javafx-base:11:$platform"
  compile "org.openjfx:javafx-graphics:11:$platform"
  compile "org.openjfx:javafx-controls:11:$platform"
  compile "org.openjfx:javafx-fxml:11:$platform"
  testCompile 'junit:junit:4.12'

  testCompile 'org.mockito:mockito-core:2.+'
  testCompile 'de.saxsys:jfx-testrunner:1.2'
  testCompile 'org.apache.commons:commons-text:1.6'
  testCompile "org.junit.jupiter:junit-jupiter-api:$junitJupiterVersion"
  testCompile "org.junit.jupiter:junit-jupiter-engine:$junitJupiterVersion"
  testCompile 'org.hamcrest:hamcrest-all:1.3'
}

And the module-info.java:

module open.terms.client.jfx {
  requires org.transentials.cardhouse.commons;
  requires com.google.common;
  requires org.apache.commons.lang3;
  requires org.hibernate.orm.core;
  requires java.persistence;
  requires slf4j.api;
  requires javafx.graphics;
  requires javafx.fxml;
  requires java.desktop;
}

Can someone explain to me what the compiler wants to tell me by this?

Sletten answered 29/11, 2018 at 21:48 Comment(0)
B
13

With the required list of dependencies, if you remove all the required modules from the module-info, the IDE will still complain with the same error:

Module '' reads package 'javafx.beans' from both 'javafx.base' and 'javafx.base'

So the problem is not in your module-info, but in your dependencies. If you comment out all of them, except the JavaFX ones, the problem is gone.

This means that some dependency is carrying some unnecessary JavaFX dependency.

I've managed to isolate the problem by commenting only the first dependency:

compile 'org.transentials:cardhouse-commons:1.1.1'

So the question is why is this happening and how can we fix it.

If you go to Maven Central repo it shows the GitHub repo of the dependency, where you can find the build.gradle file and its module-info.

As expected, it uses JavaFX:

compile "org.openjfx:javafx-base:11:$platform"

and it also requires javafx.base in its module-info.

When you consume this artifact with your dependencies you are importing their javafx.base import, along with yours from your JavaFX dependencies and there is the conflict.

The fastest way to solve the issue is just changing this in your build:

compile 'org.transentials:cardhouse-commons:1.1.1'

to this:

compile ('org.transentials:cardhouse-commons:1.1.1') {
    exclude group: 'org.openjfx'
}

so you will exclude its JavaFX dependencies and will use yours.

A more permanent fix will be changing the artifact org.transentials:cardhouse-commons's module-info to:

`requires transitive javafx.base`

You can read about the use of transitive here.

An issue should be reported to the author.

Note

As an aside, you can use the javafx gradle plugin to take care of all the related JavaFX parts of the build, simplifying it to:

plugins {
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.5'
}

repositories {
    mavenCentral()
}

dependencies {
    compile ('org.transentials:cardhouse-commons:1.1.1') {
        exclude group: 'org.openjfx'
    }
    compile files('libs/cardhouse-commons-master-1.1.1.jar')
    ...
    compile 'javax.validation:validation-api:2.0.1.Final'
}

javafx {
    modules = [ 'javafx.controls', 'javafx.fxml' ]
}

mainClassName = 'open.terms.client.jfx.Main'

The OpenJFX docs already make use of this plugin.

Borderline answered 30/11, 2018 at 17:13 Comment(12)
Almost, but I don't agree on your "cross-platform fix". I'd rather not export javafx dependencies at all.Pirn
Well, the actual code being in gradle, the pom.xml generated by central was a little different. I would though not suggest bringing in javafx.base as a transitive dependency and rather solve it using the plugin as updated in the documentation. Maybe this change shall help github.com/transentials/cardhouse-commons/pull/1/filesAili
The problem will still be the same. The plugin won't modify the module-info, and therefore you will be exporting exactly the same artifact as you did before. I've modified the project with transitive, and that works for me.Pirn
@nullpointer You can see this case: it is a library that requires JavaFX but it doesn't export it as dependency, so the library can be added as regular dependency to other final apps.Pirn
Ya, I get it. I believe my suggestion would've made more sense if the project was non-modular. Right?Aili
Using cross-platform solutions works for final projects that you want to distribute via a fat jar. While you should use jlink, or the jpackager (when available) instead, these are platform specific, of course. In terms of libraries, I'm not fan of having JavaFX with them, your final project that consume them will be a JavaFX project after all, and it will include itself these dependencies. But I've seen some other project that doesn't realize this issue and generates this kind of problems in the final user.Pirn
Thank you guys for all your help! I'm the author of the library in question, too, so there is nothing keeping it form being fixed! It's my first try to create a Maven artifact and my first attempt to migrate to modularized Java application and JDK 11, apparently a not so educated try, though. Thanks again, that you try helping me. I'll read through your comments at the weekend and tell you about the result but might have some other questions. Thanks!Sletten
@JoséPereda I just found the time to try your "more permanent fix" (based on @nullpointer's pull request) and now I get an error "Error:java: module not found: javafx.base" and I am only able to add some javafx.baseEmpty to the modules-info.java. I probably misunderstood something?Sletten
Where do you get that error? In your final app? It means that you don't have JavaFX dependencies yet, so you will have to include them as usual (as in my final note about the build.gradle file).Pirn
@JoséPereda I added as well the JavaFX Gradle plugin, now I do not get the error anymore. Now I only have to deal with "split packages" from libraries which are not mine. I am not sure if that can be handled at all.Sletten
You may want to add to your build.gradle file something like run { doFirst { jvmArgs = [...] } }. Then you will have to work with --patch-module to fix those packages.Pirn
Where is the build file in my java project?Sian
A
2

The error reads, that you've ended up placing same module twice in your modulepath for JavaFX.

The chances are that you might have placed both the jmods for the OpenJFX as well as the OpenJFX SDK/lib on your modulepath.

The JavaFX 11 runtime is available as

  • a platform-specific SDK

  • as a number of jmods and

  • as a set of artifacts in maven central.

Either(one) of these three should be sufficient enough to work with further depending on how you are planning to build your application - modular or non-modular.

Edit 1 [Conceptual Improvement]

In your build.gradle, you should just need to have dependencies over

compile "org.openjfx:javafx-controls:11:$platform"
compile "org.openjfx:javafx-fxml:11:$platform"

since the module, javafx.base and javafx.graphics are transitively present in the module path via javafx-controls anyway. Also, you must ensure, given these dependencies you are not adding any libraries under Project Settings > Libraries.

Edit 2 [Extensible improvement]

Following the documentation at OpenJFX, you can make use of the plugin and get rid of the openjfx dependencies

plugins {
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.5'
}

javafx {
    modules = [ 'javafx.controls', 'javafx.fxml' ]
}

dependencies {
    // all dependencies except openjfx
}

Edit 3 [Hands on]

The actual culprit in your example is the dependency

compile 'org.transentials:cardhouse-commons:1.1.1'

disabling this fixes the issue. You might want to raise it to the library owner(or fix this if you own it) to ensure that it doesn't bring along javafx.base module along with. To be precise this dependency is bringing in the org.openjfx:javafx-base:linux:11.0.1 as a dependency the reason being clear in their pom.xml dependencies.

Aili answered 30/11, 2018 at 1:38 Comment(16)
I only use the artifacts in Maven Central, no SDK, and no jmod.Sletten
@Sletten can you update the question with how you are executing/compiling the project with the effective pom.xml content as well in that case?Aili
@Sletten Updated the answer as well, you should ensure that no libraries under project settings.Aili
Removing javafx.base from module-info.java resolved the problem - now I am left with those annoying <i>Split package</i> issue.Sletten
@nullpointer about your edit: you need all the modules, when you have classifiers, transitive dependencies are not resolved (using Gradle).Pirn
@JoséPereda I am not very good at gradle honestly, but does the platform here mean the classifier?Aili
@Sletten Cool, the update should be the answer to this question then. On the other hand, split package issues have been a work in progress for a lot of libraries I've seen. Maybe you would find the solution to that as well. But I would insist researching on that part before you ask that on SO(just in case).Aili
@nullpointer yes, that's the classifier. It was explained in the OpenJFX docs, but since we use the javafx plugin, that is hidden to the user now.Pirn
@Sletten If removing javafx.base solves the issue, it may have to do with some other dependency already adding it. You can run ./gradlew dependencies and see if that was the case?Pirn
@JoséPereda Yes, I could see the difference in the current documentation and what it used to be some time ago. Thanks for the info.Aili
@nullpointer Okay, that did not solve my problem, I still have the original problem; I updated my original question.Sletten
@Sletten does ./gradlew run work fine for you? Are you sure the JDK configured for your project is JDK11 or above?Aili
@nullpointer Well, now, after emptying the module-info.java and manually adding the required modules one by one I ended up with a list of modules which seems to work. I still cannot run it since there is still the split package problem I just not coming over.Sletten
@Sletten I found the actual culprit in your case by actually giving out all your dependencies a try. Though I am not sure of a quick fix for that, but that would need a fix at the library org.transentials:cardhouse-commons:1.1.1 possibly.Aili
@nullpointer I did find that too, I was writing my answer while you were commenting. It provides a workaround and a permanent fix (in the given artifact). Does it make sense to you?Pirn
@Sletten Maybe this change shall help github.com/transentials/cardhouse-commons/pull/1/files. Do take a look at Jose's answer which alternatively suggests using a transitive directive along with javafx.base in your library.Aili

© 2022 - 2024 — McMap. All rights reserved.