Jigsaw test dependencies in classpath: why is the superclass in another JAR not accessible?

224 views Asked by At

I am currently testing to migrate an existing Java 8 (Maven) project to Java 9 / Jigsaw, using jdk9-ea+147 and maven-compiler-plugin 3.6.0.

I have converted the src directory to a module and left the test directory non-modular.

During testCompile I get an unexpected error:

error: build() in ExtractedArtifactStoreBuilder is defined in an inaccessible class or interface

Of course I have checked that both the ExtractedArtifactStoreBuilder is public. build() is inherited from its (public) superclass and public as well. The code compiles and runs fine in JDK 8.

ExtractArtifactStoreBuilder is defined in a different 3rd partry JAR than its superclass, but Maven correctly puts both in the classpath. Confusingly, the superclass has the same classname (but resides in a different package)

As far as I can see, I should be able to access public inherited methods in my test code. So is this a bug in the jdk9 early access version?


Edit: hoping for better comprehensibility, here is a little abstraction of the involved JARs and classes, with less confusing naming and unimportant stuff left out (for the actual dependencies, see below):

process.jar

public ProcessStoreBuilder
    public ProcessStoreBuilder download(...) // returns "this"
    public ... build()

mongo.jar

public MongoStoreBuilder extends ProcessStoreBuilder

src/test/java/ExampleTest

mongoStoreBuilder.download(...).build()
//                              ^ breaks at compile time, saying that
//                              ProcessStoreBuilder#build() is not accessible

I have been able to reproduce the behavior in a minimal setup:

pom.xml (excerpt)

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.6.0</version>
            <configuration>
                <source>9</source>
                <target>9</target>
                <debug>true</debug>
                <optimize>true</optimize>
            </configuration>
        </plugin>
    </plugins>
</build>

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>de.flapdoodle.embed</groupId>
        <artifactId>de.flapdoodle.embed.mongo</artifactId>
        <version>1.50.0</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>de.flapdoodle.embed</groupId>
        <artifactId>de.flapdoodle.embed.process</artifactId>
        <version>1.50.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

src/main/java/module-info.java

module com.mycompany.example.testdependencyexample {}

src/test/java/ExampleTest.java (excerpt)

@Before
public void setUp() throws Exception {

    // both `download` and `build` are inherited from the superclass

    // the following does work
    // de.flapdoodle.embed.mongo.config.ExtractedArtifactStoreBuilder
    ExtractedArtifactStoreBuilder easb =  new ExtractedArtifactStoreBuilder();
    easb.download(new DownloadConfigBuilder().build());
    easb.build();

    // but this does not
    // download returns the same instance but has the superclass as return type
    // de.flapdoodle.embed.process.store.ExtractedArtifactStoreBuilder
    // the compiler can't see the `build` method of the superclass
    new ExtractedArtifactStoreBuilder()
            .download(new DownloadConfigBuilder().build())
            .build();

}
0

There are 0 answers