jodastephen / jpms-module-names

Module names for the Java Module System (JPMS)
MIT License
37 stars 6 forks source link

Maven Repository Index/View By Module Name #7

Closed sormuras closed 6 years ago

sormuras commented 6 years ago

Manually collecting and mapping Maven coordinates to JPMS module names is a good first step.

What we need is "module name first" approach, meaning a Maven repository should resolve an unique module name to its group and artifact ID automatically. With that functionality you could specify your dependencies like:

    <dependencies>
        <dependency>
            <module>org.slf4j.api</groupId>
            <version>1.8.0</version>
        </dependency>
        [...]
        <dependency>
            <scope>test</scope>
            <module>org.junit.platform.console</groupId>
            <version>1.0.2</version>
        </dependency>
    </dependencies>

What do you think about this idea?

Who to address to spike such a feature for a Maven repository? @rfscholte? ;)

rfscholte commented 6 years ago

This means you need to introduce a new repository layout, which is based on an Artifact. With other words: still based on groupId+artifactId. Also this must be translated to groupId+artifactId when generating a consumer pom. This concept is far from ready. I doubt it is worth trying to implement this. Doing it correct will mean rewriting a huge amount of the Maven codebase. Even 2 weeks of xmas holidays is not enough, but it'll give you a huge amount of experience ;)

sormuras commented 6 years ago

Mh okay. Perhaps the proposal is three steps too much ... but instead of creating the index manually like done here, an artifact and its associated module name relation should be generated automatically by "the repository". Something similar to the http://central.maven.org/maven2/archetype-catalog.xml:

module-catalog.xml

<modules>
  <module>
    <name>org.slf4j.api</name>
    <group>org.slf4j</group>
    <artifact>slf4j-api</artifact>
  </module>

</modules>

Build tools (plugins) may now evaluate that information and resolve the module name to groupId+artifactId relation. Only the version is needed as a user input.

Here is an example of manually creating such a mapping:

https://github.com/forax/pro/blob/968bd596de2e7411265484897596b6c385c17b04/src/main/java/com.github.forax.pro.bootstrap/com/github/forax/pro/bootstrap/Bootstrap.java#L90-L99

jodastephen commented 6 years ago

I see this repo as a stopgap until http://search.maven.org/ and similar publish the module name. Doing this as a github project will not scale to the number of artifacts in Maven Central.

What is interesting to think about is whether it makes sense to try and go from a module name to a group+artifact. While each module does tend to have a default artifact, it is possible for other artifacts to also be used (patched versions, or variants of an API for example). I suspect its not, and I haven't come up with a viable suggestion yet.

sormuras commented 6 years ago

A proof-of-concept spike is available here: https://github.com/sormuras/bach/tree/master/demo/03-modules-first -- might compile it into a Gradle Plugin, which comes with a default module-maven.properties populated from the table created in this project. Or by crawling the "central"... ;)

Gradle Dependency with Module Names


String resolve(String module) {
    return module2Maven.get(module) + ':' + module2Version.get(module)
}

dependencies {
    compile resolve('org.apache.commons.lang3')
    compile resolve('org.slf4j')
    compile resolve('org.apiguardian.api')
    testCompile resolve('org.junit.jupiter.api')
    testRuntime resolve('org.junit.jupiter.engine')
}

module-maven.properties

# module = group:artifact
org.apache.commons.lang3 = org.apache.commons:commons-lang3
org.apiguardian.api = org.apiguardian:apiguardian-api
org.junit.jupiter.api = org.junit.jupiter:junit-jupiter-api
org.junit.jupiter.engine = org.junit.jupiter:junit-jupiter-engine
org.junit.platform.commons = org.junit.platform:junit-platform-commons
org.junit.platform.engine = org.junit.platform:junit-platform-engine
org.junit.platform.launcher = org.junit.platform:junit-platform-launcher
org.opentest4j = org.opentest4j:opentest4j
org.slf4j = org.slf4j:slf4j-api

module-version.properties

# module = version
org.apache.commons.lang3 = 3.7
org.apiguardian.api = 1.0.0
org.junit.jupiter.api = 5.1.0-SNAPSHOT
org.junit.jupiter.engine = 5.1.0-SNAPSHOT
org.junit.platform.commons = 1.1.0-SNAPSHOT
org.junit.platform.engine = 1.1.0-SNAPSHOT
org.junit.platform.launcher = 1.1.0-SNAPSHOT
org.opentest4j = 1.0.0
org.slf4j = 1.8.0-beta0
sormuras commented 6 years ago

https://github.com/jodastephen/jpms-module-names/tree/master/generated now contains module-maven.properties and module-version.properties. A simple Gradle plugin is in the works...

sormuras commented 6 years ago

Gradle demo now resides in demo/gradle:

apply plugin: 'java'
apply from: 'https://.../jpms-module-names/master/demo/gradle/module-maven.gradle'
// ...
dependencies {
    compile     mod2mav('org.apache.commons.lang3')
    compile     mod2mav('org.joda.beans')
    compile     mod2mav('org.opentest4j')
    compile     mod2mav('org.slf4j')
    compile     mod2mav('org.apiguardian.api')
    testCompile mod2mav('org.junit.jupiter.api')
    testRuntime mod2mav('org.junit.jupiter.engine')
}
// ...