4

I am trying to run the test for java applications (with module system enabled) using Gradle and getting the following error.

java.lang.IllegalAccessError: class org.junit.platform.launcher.core.LauncherFactory (in unnamed module @0x7cd3a5) cannot access class org.junit.platform.commons.util.Preconditions (in module org.junit.platform.commons) because module org.junit.platform.commons does not export org.junit.platform.commons.util to unnamed module @0x7cd3a5

Error says module org.junit.platform.commons does not export org.junit.platform.commons.util This is how my build file looks like:

import org.springframework.boot.gradle.plugin.SpringBootPlugin

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.3.1.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
    id "org.beryx.jlink" version "2.21.0"
    id "org.javamodularity.moduleplugin" version "1.6.0"
}

repositories {
    gradlePluginPortal()
    jcenter()
}

sourceCompatibility = JavaVersion.VERSION_14
targetCompatibility = JavaVersion.VERSION_14
tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

jar {
    enabled = true;
}
application{
    mainModule='com.sudhir.registration'
}

test {
    useJUnitPlatform()
}

configurations {
    springFactoriesHolder { transitive = false }
}

dependencyManagement {
    imports {
        mavenBom SpringBootPlugin.BOM_COORDINATES
    }
}

dependencies {
    springFactoriesHolder 'org.springframework.boot:spring-boot-actuator-autoconfigure'
    springFactoriesHolder 'org.springframework.boot:spring-boot-autoconfigure'
    springFactoriesHolder 'org.springframework.boot:spring-boot'

    implementation 'org.springframework.boot:spring-boot-starter-web'

    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
        exclude group: 'com.vaadin.external.google', module: 'android-json'
    }
}

mainClassName = "com.sudhir.registration.ApiApplication"


prepareMergedJarsDir.doLast {
    // extract and merge META-INF/spring.factories from springFactoriesHolder
    def factories = configurations.springFactoriesHolder.files.collect {
        def props = new Properties()
        props.load(zipTree(it).matching { include 'META-INF/spring.factories' }.singleFile.newInputStream())
        props
    }
    def mergedProps = new Properties()
    factories.each { props ->
        props.each { key, value ->
            def oldVal = mergedProps[key]
            mergedProps[key] = oldVal ? "$oldVal,$value" : value
        }
    }
    def content = mergedProps.collect { key, value ->
        def v = (value as String).replace(',', ',\\\n')
        "$key=$v"
    }.join('\n\n')
    mkdir("$jlinkBasePath/META-INF")
    new File("$jlinkBasePath/META-INF/spring.factories").text = content

    // insert META-INF/spring.factories into the main jar
    ant.zip(update: "true", destfile: jar.archivePath, keepcompression: true) {
        fileset(dir: "$jlinkBasePath", includes: 'META-INF/**')
    }
}

jlink {
    imageZip = file("$buildDir/image-zip/registration-service-image.zip")
    options = ['--strip-java-debug-attributes', '--compress', '2', '--no-header-files', '--no-man-pages']
    forceMerge 'jaxb-api', 'byte-buddy', 'classgraph'
    mergedModule {

        uses 'ch.qos.logback.classic.spi.Configurator'

        excludeRequires 'com.fasterxml.jackson.module.paramnames'
        excludeProvides implementation: 'com.sun.xml.bind.v2.ContextFactory'
        excludeProvides servicePattern: 'javax.enterprise.inject.*'
        excludeProvides service: 'org.apache.logging.log4j.spi.Provider'
        excludeProvides servicePattern: 'reactor.blockhound.integration.*'
    }
    launcher {
        name = 'run'
        jvmArgs = [
                '--add-reads', 'registration.service.merged.module=com.sudhir.registration',
                '-cp', 'config/',
        ]
    }
}

tasks.jlink.doLast {
    copy {
        from "src/main/resources"
        into "$imageDir.asFile/bin/config"
    }

    copy {
        from "$buildDir/classes/java/main/com/sudhir/registration"
        into "$imageDir.asFile/bin/config/com/sudhir/registration/for-spring-classpath-scanner"
    }
}


However, I am able to run specific tests in IntelliJ. I think it's because Intellij is using classpath instead of module path.

I am using gradle-module-system plugin to build, test and run. sample code can be found here.

Can someone please assist me how to deal with this issue. I am very new to using java module system.

Sudhir Kumar
  • 163
  • 2
  • 15
  • [this may be](https://stackoverflow.com/questions/46613214/java-9-maven-junit-does-test-code-need-module-info-java-of-its-own-and-wher/63386799#63386799) – Eugene Oct 29 '20 at 18:55

1 Answers1

0

Not quite sure on the reason of this problem. These threads may help to understand it: this, this, this or this

But this is what helped me in a similar case:

test {
    moduleOptions {
        runOnClasspath = true
    }
    useJUnitPlatform()
}

(Adding moduleOptions setting to the test task)