3

I created a web application. I am using Gradle. I am new to Gradle and I am trying to migrate one of my projects to Java 9 module system. I moved all the jars to module path instead of the classpath. Here is the snippet of my build.gradle

plugins {
    id 'java-library'
    id 'eclipse-wtp'
    id 'war'
}

ext {
    //logging
    log4jGroupId = "org.apache.logging.log4j"
    log4jVersion = "2.11.0"
    .....
    moduleName = "pk.training.basit.kanban"
}

dependencies {
    // Unit Testing
    testImplementation group: 'junit', name: 'junit', version: junitVersion
    testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: junitJupiterEngineVersion
    implementation group: log4jGroupId, name: 'log4j-api', version: log4jVersion
    .....
    ['log4j-core', 'log4j-jcl', 'log4j-slf4j-impl', 'log4j-web'].each {
        runtime "${log4jGroupId}:$it:${log4jVersion}"
    }

    implementation group: 'javax.transaction', name: 'javax.transaction-api', version: javaxTransactionApiVersion

    implementation (group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: jaxbVersion) {
    exclude group: 'org.jvnet.staxex', module: 'stax-ex'
    }
    ...   
}

eclipse.classpath.file {
    whenMerged {
        entries.findAll { isModule(it) }.each { it.entryAttributes['module'] = 'true' }
    }
}

boolean isModule(entry) {
    // filter java 9 modules
    entry.kind == 'lib'  // Only libraries can be modules
}

eclipse.wtp.facet.file.withXml { facetXml ->
    def root = facetXml.asNode()
    root.installed.find { it.@facet == 'jst.java' }.@version = '9'
    root.installed.find { it.@facet == 'jst.web' }.@version = '3.1'
}

compileJava {
    inputs.property("moduleName", moduleName)
    doFirst {
        options.compilerArgs = [
            '--module-path', classpath.asPath,
        ]
        classpath = files()  // Clears the classpath property by creating an empty file collection
    }
}

compileTestJava {
    inputs.property("moduleName", moduleName)
    doFirst {
        options.compilerArgs = [
            '--module-path', classpath.asPath,      // This is the default value for the classpath property used as the --module-path.
            '--add-modules', 'org.junit.jupiter.api',  // junit5 automatic module specific
            '--add-modules', 'java.xml.bind', // jaxb specific
            '--add-reads', "$moduleName=org.junit.jupiter.api", // allow junit to read your module
            '--patch-module', "$moduleName=" + files(sourceSets.test.java.srcDirs).asPath, // Adds the test source files to the org.gradle.actors module.
        ]
        classpath = files()
    }
}

test {
    inputs.property("moduleName", moduleName)
    doFirst {
        jvmArgs = [
            '--module-path', classpath.asPath, 
            '--add-modules', 'ALL-MODULE-PATH', 
            '--add-reads', "$moduleName=org.junit.jupiter.api", 
            '--patch-module', "$moduleName=" + files(sourceSets.test.java.outputDir).asPath, 
        ]
        classpath = files()
    }
}

Now if I execute the gradle build or buildDependents or testClasses task then I get the following errors

module not found: junit --> requires junit;
module not found: log4j.api -->  requires log4j.api;
module not found: org.apache.logging.log4j.web --> requires org.apache.logging.log4j.web;
error: the unnamed module reads package javax.transaction.xa from both java.sql and javax.transaction.api
error: the unnamed module reads package javax.activation from both java.activation and activation
error: the unnamed module reads package com.sun.xml.bind from both jaxb.runtime and jaxb.core
error: module spring.web reads package javax.transaction.xa from both javax.transaction.api and java.sql
error: module spring.security.core reads package javax.transaction.xa from both javax.transaction.api and java.sql
....

So Why I am getting module not found exception for jUnit, log4j.api and org.apache.logging.log4j.web. I checked in the module path and jars are there.

Second I read about split packages. My question is as I know from the error that the two jars are java.sql and javax.transaction.api and jaxb.runtime and jaxb.core and similary for other jars.

Can I make a Gradle task that merges these two jars into one and includes that one jar on the module path so these errors can be removed? Or there is another way to resolve such kind of errors?

Is it possible to move some jars to module path and some jars to the classpath? And how you can find which jars to move module path and which jars to move classpath?

Thank you

Farhana Naaz Ansari
  • 7,524
  • 26
  • 65
  • 105
Basit
  • 8,426
  • 46
  • 116
  • 196
  • Just a suggestion to debug, you can [try and add show module resolution flag](https://stackoverflow.com/questions/48339598/list-the-modules-resolved-during-the-application-startup) to the jvm args as well for better understanding of what all modules are actually resolved, – Naman Apr 25 '18 at 17:21
  • Did you solve your problem? – Feri Nov 14 '18 at 04:59

0 Answers0