Skip to content

Use manifest entry for java 9 module name#3743

Merged
swankjesse merged 11 commits intosquare:masterfrom
yschimke:module_names
Feb 4, 2018
Merged

Use manifest entry for java 9 module name#3743
swankjesse merged 11 commits intosquare:masterfrom
yschimke:module_names

Conversation

@yschimke
Copy link
Collaborator

No description provided.

@yschimke
Copy link
Collaborator Author

$ for i in */target/*-SNAPSHOT.jar; do echo $i; unzip -q -c $i META-INF/MANIFEST.MF | grep Automatic-Module-Name ; done
benchmarks/target/benchmarks-3.10.0-SNAPSHOT.jar
Automatic-Module-Name: benchmarks
mockwebserver/target/mockwebserver-3.10.0-SNAPSHOT.jar
Automatic-Module-Name: mockwebserver
okcurl/target/okcurl-3.10.0-SNAPSHOT.jar
warning [okcurl/target/okcurl-3.10.0-SNAPSHOT.jar]:  58 extra bytes at beginning or within zipfile
  (attempting to process anyway)
Automatic-Module-Name: okcurl
okhttp-android-support/target/okhttp-android-support-3.10.0-SNAPSHOT.jar
Automatic-Module-Name: okhttp-android-support
okhttp-apache/target/okhttp-apache-3.10.0-SNAPSHOT.jar
Automatic-Module-Name: okhttp-apache
okhttp-logging-interceptor/target/logging-interceptor-3.10.0-SNAPSHOT.jar
Automatic-Module-Name: logging-interceptor
okhttp-testing-support/target/okhttp-testing-support-3.10.0-SNAPSHOT.jar
Automatic-Module-Name: okhttp-testing-support
okhttp-tests/target/okhttp-tests-3.10.0-SNAPSHOT.jar
Automatic-Module-Name: okhttp-tests
okhttp-urlconnection/target/okhttp-urlconnection-3.10.0-SNAPSHOT.jar
Automatic-Module-Name: okhttp-urlconnection
okhttp/target/okhttp-3.10.0-SNAPSHOT.jar
Automatic-Module-Name: okhttp

@yschimke yschimke mentioned this pull request Dec 28, 2017
@yschimke
Copy link
Collaborator Author

It seems like we are happy that the names of commonly used modules are unique enough e.g. okhttp, mockwebserver, okhttp-urlconnection. But at the moment just renaming the jar files will change the names.

Defining these based on advice here
http://branchandbound.net/blog/java/2017/12/automatic-module-name/
and
http://blog.joda.org/2017/05/java-se-9-jpms-automatic-modules.html

Do not release to Maven Central a modular jar file that depends on an automatic module, unless the automatic module has an "Automatic-Module-Name" MANIFEST.MF entry.

Copy link
Collaborator

@swankjesse swankjesse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable, though I must admit I don't grasp the benefits or consequences. What happens if we just sit out of Java 9 modules? I’m anxious about the way this plays out for libraries like Moshi that do more aggressive reflection.

@yschimke
Copy link
Collaborator Author

yschimke commented Dec 29, 2017

We get the same automatic names as the default names, but things break if someone renames a JAR file. These are not great names (namespaced etc), but I think the Jars that people use externally are good enough.

@kashike
Copy link

kashike commented Jan 27, 2018

@yschimke yschimke requested a review from JakeWharton January 28, 2018 15:27
@yschimke
Copy link
Collaborator Author

Let's agree this before landing. I'm ok with either, but want this at minimum so a simple jar file rename doesn't change the module names.

@JakeWharton
Copy link
Collaborator

I agree these are not sufficient. I would do com.squareup.okhttp3 and com.squareup.okhttp3.mockwebserver, etc.

@yschimke
Copy link
Collaborator Author

yschimke commented Jan 28, 2018

$ find */target -name \*.jar -exec echo {} \; -exec /Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/jar --describe-module --file {} \;
benchmarks/target/benchmarks-3.10.0-SNAPSHOT.jar
No module descriptor found. Derived automatic module.

benchmarks@3.10.0-SNAPSHOT automatic
requires java.base mandated
contains okhttp3.benchmarks

mockwebserver/target/mockwebserver-3.10.0-SNAPSHOT-jar-with-dependencies.jar
No module descriptor found. Derived automatic module.

mockwebserver@3.10.0-SNAPSHOT-jar-with-dependencies automatic
requires java.base mandated
contains junit.extensions
contains junit.framework
contains junit.runner
contains junit.textui
contains okhttp3
contains okhttp3.internal
contains okhttp3.internal.cache
contains okhttp3.internal.cache2
contains okhttp3.internal.connection
contains okhttp3.internal.http
contains okhttp3.internal.http1
contains okhttp3.internal.http2
contains okhttp3.internal.io
contains okhttp3.internal.platform
contains okhttp3.internal.publicsuffix
contains okhttp3.internal.tls
contains okhttp3.internal.ws
contains okhttp3.mockwebserver
contains okio
contains org.bouncycastle
contains org.bouncycastle.apache.bzip2
contains org.bouncycastle.asn1
contains org.bouncycastle.asn1.bc
contains org.bouncycastle.asn1.cmp
contains org.bouncycastle.asn1.cms
contains org.bouncycastle.asn1.cms.ecc
contains org.bouncycastle.asn1.crmf
contains org.bouncycastle.asn1.cryptopro
contains org.bouncycastle.asn1.dvcs
contains org.bouncycastle.asn1.eac
contains org.bouncycastle.asn1.esf
contains org.bouncycastle.asn1.ess
contains org.bouncycastle.asn1.gnu
contains org.bouncycastle.asn1.iana
contains org.bouncycastle.asn1.icao
contains org.bouncycastle.asn1.isismtt
contains org.bouncycastle.asn1.isismtt.ocsp
contains org.bouncycastle.asn1.isismtt.x509
contains org.bouncycastle.asn1.kisa
contains org.bouncycastle.asn1.microsoft
contains org.bouncycastle.asn1.misc
contains org.bouncycastle.asn1.mozilla
contains org.bouncycastle.asn1.nist
contains org.bouncycastle.asn1.ntt
contains org.bouncycastle.asn1.ocsp
contains org.bouncycastle.asn1.oiw
contains org.bouncycastle.asn1.pkcs
contains org.bouncycastle.asn1.sec
contains org.bouncycastle.asn1.smime
contains org.bouncycastle.asn1.teletrust
contains org.bouncycastle.asn1.tsp
contains org.bouncycastle.asn1.ua
contains org.bouncycastle.asn1.util
contains org.bouncycastle.asn1.x500
contains org.bouncycastle.asn1.x500.style
contains org.bouncycastle.asn1.x509
contains org.bouncycastle.asn1.x509.qualified
contains org.bouncycastle.asn1.x509.sigi
contains org.bouncycastle.asn1.x9
contains org.bouncycastle.crypto
contains org.bouncycastle.crypto.agreement
contains org.bouncycastle.crypto.agreement.jpake
contains org.bouncycastle.crypto.agreement.kdf
contains org.bouncycastle.crypto.agreement.srp
contains org.bouncycastle.crypto.commitments
contains org.bouncycastle.crypto.digests
contains org.bouncycastle.crypto.ec
contains org.bouncycastle.crypto.encodings
contains org.bouncycastle.crypto.engines
contains org.bouncycastle.crypto.examples
contains org.bouncycastle.crypto.generators
contains org.bouncycastle.crypto.io
contains org.bouncycastle.crypto.kems
contains org.bouncycastle.crypto.macs
contains org.bouncycastle.crypto.modes
contains org.bouncycastle.crypto.modes.gcm
contains org.bouncycastle.crypto.paddings
contains org.bouncycastle.crypto.params
contains org.bouncycastle.crypto.parsers
contains org.bouncycastle.crypto.prng
contains org.bouncycastle.crypto.prng.drbg
contains org.bouncycastle.crypto.signers
contains org.bouncycastle.crypto.tls
contains org.bouncycastle.crypto.util
contains org.bouncycastle.i18n
contains org.bouncycastle.i18n.filter
contains org.bouncycastle.jcajce
contains org.bouncycastle.jcajce.io
contains org.bouncycastle.jcajce.provider.asymmetric
contains org.bouncycastle.jcajce.provider.asymmetric.dh
contains org.bouncycastle.jcajce.provider.asymmetric.dsa
contains org.bouncycastle.jcajce.provider.asymmetric.dstu
contains org.bouncycastle.jcajce.provider.asymmetric.ec
contains org.bouncycastle.jcajce.provider.asymmetric.ecgost
contains org.bouncycastle.jcajce.provider.asymmetric.elgamal
contains org.bouncycastle.jcajce.provider.asymmetric.gost
contains org.bouncycastle.jcajce.provider.asymmetric.ies
contains org.bouncycastle.jcajce.provider.asymmetric.rsa
contains org.bouncycastle.jcajce.provider.asymmetric.util
contains org.bouncycastle.jcajce.provider.asymmetric.x509
contains org.bouncycastle.jcajce.provider.config
contains org.bouncycastle.jcajce.provider.digest
contains org.bouncycastle.jcajce.provider.keystore
contains org.bouncycastle.jcajce.provider.keystore.bc
contains org.bouncycastle.jcajce.provider.keystore.pkcs12
contains org.bouncycastle.jcajce.provider.symmetric
contains org.bouncycastle.jcajce.provider.symmetric.util
contains org.bouncycastle.jcajce.provider.util
contains org.bouncycastle.jcajce.spec
contains org.bouncycastle.jce
contains org.bouncycastle.jce.examples
contains org.bouncycastle.jce.exception
contains org.bouncycastle.jce.interfaces
contains org.bouncycastle.jce.netscape
contains org.bouncycastle.jce.provider
contains org.bouncycastle.jce.spec
contains org.bouncycastle.math.ec
contains org.bouncycastle.ocsp
contains org.bouncycastle.pqc.asn1
contains org.bouncycastle.pqc.crypto
contains org.bouncycastle.pqc.crypto.gmss
contains org.bouncycastle.pqc.crypto.gmss.util
contains org.bouncycastle.pqc.crypto.mceliece
contains org.bouncycastle.pqc.crypto.rainbow
contains org.bouncycastle.pqc.crypto.rainbow.util
contains org.bouncycastle.pqc.jcajce.provider
contains org.bouncycastle.pqc.jcajce.provider.gmss
contains org.bouncycastle.pqc.jcajce.provider.mceliece
contains org.bouncycastle.pqc.jcajce.provider.rainbow
contains org.bouncycastle.pqc.jcajce.provider.util
contains org.bouncycastle.pqc.jcajce.spec
contains org.bouncycastle.pqc.math.linearalgebra
contains org.bouncycastle.util
contains org.bouncycastle.util.encoders
contains org.bouncycastle.util.io
contains org.bouncycastle.util.io.pem
contains org.bouncycastle.util.test
contains org.bouncycastle.x509
contains org.bouncycastle.x509.examples
contains org.bouncycastle.x509.extension
contains org.bouncycastle.x509.util
contains org.hamcrest
contains org.hamcrest.core
contains org.hamcrest.internal
contains org.junit
contains org.junit.experimental
contains org.junit.experimental.categories
contains org.junit.experimental.max
contains org.junit.experimental.results
contains org.junit.experimental.runners
contains org.junit.experimental.theories
contains org.junit.experimental.theories.internal
contains org.junit.experimental.theories.suppliers
contains org.junit.internal
contains org.junit.internal.builders
contains org.junit.internal.matchers
contains org.junit.internal.requests
contains org.junit.internal.runners
contains org.junit.internal.runners.model
contains org.junit.internal.runners.rules
contains org.junit.internal.runners.statements
contains org.junit.matchers
contains org.junit.rules
contains org.junit.runner
contains org.junit.runner.manipulation
contains org.junit.runner.notification
contains org.junit.runners
contains org.junit.runners.model
contains org.junit.runners.parameterized
contains org.junit.validator

mockwebserver/target/mockwebserver-3.10.0-SNAPSHOT.jar
No module descriptor found. Derived automatic module.

com.squareup.okhttp3.mockwebserver@3.10.0-SNAPSHOT automatic
requires java.base mandated
contains okhttp3.internal.http2
contains okhttp3.internal.tls
contains okhttp3.mockwebserver

okcurl/target/okcurl-3.10.0-SNAPSHOT-jar-with-dependencies.jar
No module descriptor found. Derived automatic module.

okcurl@3.10.0-SNAPSHOT-jar-with-dependencies automatic
requires java.base mandated
contains com.google.common.annotations
contains com.google.common.base
contains com.google.common.base.internal
contains com.google.common.cache
contains com.google.common.collect
contains com.google.common.escape
contains com.google.common.eventbus
contains com.google.common.hash
contains com.google.common.html
contains com.google.common.io
contains com.google.common.math
contains com.google.common.net
contains com.google.common.primitives
contains com.google.common.reflect
contains com.google.common.util.concurrent
contains com.google.common.xml
contains com.google.thirdparty.publicsuffix
contains edu.umd.cs.findbugs.annotations
contains io.airlift.airline
contains io.airlift.airline.model
contains javax.annotation
contains javax.annotation.concurrent
contains javax.annotation.meta
contains javax.inject
contains net.jcip.annotations
contains okhttp3
contains okhttp3.curl
contains okhttp3.internal
contains okhttp3.internal.cache
contains okhttp3.internal.cache2
contains okhttp3.internal.connection
contains okhttp3.internal.http
contains okhttp3.internal.http1
contains okhttp3.internal.http2
contains okhttp3.internal.io
contains okhttp3.internal.platform
contains okhttp3.internal.publicsuffix
contains okhttp3.internal.tls
contains okhttp3.internal.ws
contains okio
contains org.bouncycastle
contains org.bouncycastle.apache.bzip2
contains org.bouncycastle.asn1
contains org.bouncycastle.asn1.bc
contains org.bouncycastle.asn1.cmp
contains org.bouncycastle.asn1.cms
contains org.bouncycastle.asn1.cms.ecc
contains org.bouncycastle.asn1.crmf
contains org.bouncycastle.asn1.cryptopro
contains org.bouncycastle.asn1.dvcs
contains org.bouncycastle.asn1.eac
contains org.bouncycastle.asn1.esf
contains org.bouncycastle.asn1.ess
contains org.bouncycastle.asn1.gnu
contains org.bouncycastle.asn1.iana
contains org.bouncycastle.asn1.icao
contains org.bouncycastle.asn1.isismtt
contains org.bouncycastle.asn1.isismtt.ocsp
contains org.bouncycastle.asn1.isismtt.x509
contains org.bouncycastle.asn1.kisa
contains org.bouncycastle.asn1.microsoft
contains org.bouncycastle.asn1.misc
contains org.bouncycastle.asn1.mozilla
contains org.bouncycastle.asn1.nist
contains org.bouncycastle.asn1.ntt
contains org.bouncycastle.asn1.ocsp
contains org.bouncycastle.asn1.oiw
contains org.bouncycastle.asn1.pkcs
contains org.bouncycastle.asn1.sec
contains org.bouncycastle.asn1.smime
contains org.bouncycastle.asn1.teletrust
contains org.bouncycastle.asn1.tsp
contains org.bouncycastle.asn1.ua
contains org.bouncycastle.asn1.util
contains org.bouncycastle.asn1.x500
contains org.bouncycastle.asn1.x500.style
contains org.bouncycastle.asn1.x509
contains org.bouncycastle.asn1.x509.qualified
contains org.bouncycastle.asn1.x509.sigi
contains org.bouncycastle.asn1.x9
contains org.bouncycastle.crypto
contains org.bouncycastle.crypto.agreement
contains org.bouncycastle.crypto.agreement.jpake
contains org.bouncycastle.crypto.agreement.kdf
contains org.bouncycastle.crypto.agreement.srp
contains org.bouncycastle.crypto.commitments
contains org.bouncycastle.crypto.digests
contains org.bouncycastle.crypto.ec
contains org.bouncycastle.crypto.encodings
contains org.bouncycastle.crypto.engines
contains org.bouncycastle.crypto.examples
contains org.bouncycastle.crypto.generators
contains org.bouncycastle.crypto.io
contains org.bouncycastle.crypto.kems
contains org.bouncycastle.crypto.macs
contains org.bouncycastle.crypto.modes
contains org.bouncycastle.crypto.modes.gcm
contains org.bouncycastle.crypto.paddings
contains org.bouncycastle.crypto.params
contains org.bouncycastle.crypto.parsers
contains org.bouncycastle.crypto.prng
contains org.bouncycastle.crypto.prng.drbg
contains org.bouncycastle.crypto.signers
contains org.bouncycastle.crypto.tls
contains org.bouncycastle.crypto.util
contains org.bouncycastle.i18n
contains org.bouncycastle.i18n.filter
contains org.bouncycastle.jcajce
contains org.bouncycastle.jcajce.io
contains org.bouncycastle.jcajce.provider.asymmetric
contains org.bouncycastle.jcajce.provider.asymmetric.dh
contains org.bouncycastle.jcajce.provider.asymmetric.dsa
contains org.bouncycastle.jcajce.provider.asymmetric.dstu
contains org.bouncycastle.jcajce.provider.asymmetric.ec
contains org.bouncycastle.jcajce.provider.asymmetric.ecgost
contains org.bouncycastle.jcajce.provider.asymmetric.elgamal
contains org.bouncycastle.jcajce.provider.asymmetric.gost
contains org.bouncycastle.jcajce.provider.asymmetric.ies
contains org.bouncycastle.jcajce.provider.asymmetric.rsa
contains org.bouncycastle.jcajce.provider.asymmetric.util
contains org.bouncycastle.jcajce.provider.asymmetric.x509
contains org.bouncycastle.jcajce.provider.config
contains org.bouncycastle.jcajce.provider.digest
contains org.bouncycastle.jcajce.provider.keystore
contains org.bouncycastle.jcajce.provider.keystore.bc
contains org.bouncycastle.jcajce.provider.keystore.pkcs12
contains org.bouncycastle.jcajce.provider.symmetric
contains org.bouncycastle.jcajce.provider.symmetric.util
contains org.bouncycastle.jcajce.provider.util
contains org.bouncycastle.jcajce.spec
contains org.bouncycastle.jce
contains org.bouncycastle.jce.examples
contains org.bouncycastle.jce.exception
contains org.bouncycastle.jce.interfaces
contains org.bouncycastle.jce.netscape
contains org.bouncycastle.jce.provider
contains org.bouncycastle.jce.spec
contains org.bouncycastle.math.ec
contains org.bouncycastle.ocsp
contains org.bouncycastle.pqc.asn1
contains org.bouncycastle.pqc.crypto
contains org.bouncycastle.pqc.crypto.gmss
contains org.bouncycastle.pqc.crypto.gmss.util
contains org.bouncycastle.pqc.crypto.mceliece
contains org.bouncycastle.pqc.crypto.rainbow
contains org.bouncycastle.pqc.crypto.rainbow.util
contains org.bouncycastle.pqc.jcajce.provider
contains org.bouncycastle.pqc.jcajce.provider.gmss
contains org.bouncycastle.pqc.jcajce.provider.mceliece
contains org.bouncycastle.pqc.jcajce.provider.rainbow
contains org.bouncycastle.pqc.jcajce.provider.util
contains org.bouncycastle.pqc.jcajce.spec
contains org.bouncycastle.pqc.math.linearalgebra
contains org.bouncycastle.util
contains org.bouncycastle.util.encoders
contains org.bouncycastle.util.io
contains org.bouncycastle.util.io.pem
contains org.bouncycastle.util.test
contains org.bouncycastle.x509
contains org.bouncycastle.x509.examples
contains org.bouncycastle.x509.extension
contains org.bouncycastle.x509.util
main-class okhttp3.curl.Main

okcurl/target/okcurl-3.10.0-SNAPSHOT.jar
No module descriptor found. Derived automatic module.

com.squareup.okhttp3.okcurl@3.10.0-SNAPSHOT automatic
requires java.base mandated
contains okhttp3.curl

okhttp-android-support/target/okhttp-android-support-3.10.0-SNAPSHOT.jar
No module descriptor found. Derived automatic module.

com.squareup.okhttp3.androidsupport@3.10.0-SNAPSHOT automatic
requires java.base mandated
contains okhttp3
contains okhttp3.internal.huc

okhttp-apache/target/okhttp-apache-3.10.0-SNAPSHOT.jar
No module descriptor found. Derived automatic module.

com.squareup.okhttp3.apache@3.10.0-SNAPSHOT automatic
requires java.base mandated
contains okhttp3.apache

okhttp-logging-interceptor/target/logging-interceptor-3.10.0-SNAPSHOT.jar
No module descriptor found. Derived automatic module.

com.squareup.okhttp3.logginginterceptor@3.10.0-SNAPSHOT automatic
requires java.base mandated
contains okhttp3.logging

okhttp-testing-support/target/okhttp-testing-support-3.10.0-SNAPSHOT.jar
No module descriptor found. Derived automatic module.

com.squareup.okhttp3.testingsupport@3.10.0-SNAPSHOT automatic
requires java.base mandated
contains okhttp3
contains okhttp3.internal.io
contains okhttp3.testing

okhttp-tests/target/okhttp-tests-3.10.0-SNAPSHOT-jar-with-dependencies.jar
No module descriptor found. Derived automatic module.

okhttp.tests@3.10.0-SNAPSHOT-jar-with-dependencies automatic
requires java.base mandated
contains okhttp3
contains okhttp3.internal
contains okhttp3.internal.cache
contains okhttp3.internal.cache2
contains okhttp3.internal.connection
contains okhttp3.internal.http
contains okhttp3.internal.http1
contains okhttp3.internal.http2
contains okhttp3.internal.huc
contains okhttp3.internal.io
contains okhttp3.internal.platform
contains okhttp3.internal.publicsuffix
contains okhttp3.internal.tls
contains okhttp3.internal.ws
contains okio
main-class okhttp3.AutobahnTester

okhttp-tests/target/okhttp-tests-3.10.0-SNAPSHOT.jar
No module descriptor found. Derived automatic module.

okhttp.tests@3.10.0-SNAPSHOT automatic
requires java.base mandated
contains okhttp3

okhttp-urlconnection/target/okhttp-urlconnection-3.10.0-SNAPSHOT.jar
No module descriptor found. Derived automatic module.

com.squareup.okhttp3.urlconnection@3.10.0-SNAPSHOT automatic
requires java.base mandated
contains okhttp3
contains okhttp3.internal
contains okhttp3.internal.huc

okhttp/target/okhttp-3.10.0-SNAPSHOT.jar
No module descriptor found. Derived automatic module.

com.squareup.okhttp3@3.10.0-SNAPSHOT automatic
requires java.base mandated
contains okhttp3
contains okhttp3.internal
contains okhttp3.internal.cache
contains okhttp3.internal.cache2
contains okhttp3.internal.connection
contains okhttp3.internal.http
contains okhttp3.internal.http1
contains okhttp3.internal.http2
contains okhttp3.internal.io
contains okhttp3.internal.platform
contains okhttp3.internal.publicsuffix
contains okhttp3.internal.tls
contains okhttp3.internal.ws

<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>${project.groupId}.urlconnection</Automatic-Module-Name>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m trying to find out whether we can have two modules, where one is OkHttp and the other is this one, and their subpackages overlap

@yschimke
Copy link
Collaborator Author

n.b. I only added for jar files that there was a valid reason for someone to use externally. e.g. apache, urlconnection, logginginterceptor, core.

@swankjesse
Copy link
Collaborator

My only question I can’t find an answer to online – is it allowed to have one module contain subpackages of another?

@yschimke
Copy link
Collaborator Author

yschimke commented Jan 28, 2018

Good question, n.b. this change doesn't actually change what is exported etc. Just continues the default automatic rules but with a specified module name.

I don't know the answer, but I'm surprised if subpackages are a thing in Java 9 modules. Mostly the JVM seems to handle package names as arbitrary keys without any hierarchy rules.

@kashike
Copy link

kashike commented Jan 28, 2018

@jodastephen might be able to shed some light if he has some time? :-)

@jodastephen
Copy link

jodastephen commented Jan 28, 2018

It is a requirement of the Java module system that each package is in a single module. This is one reason why you would never turn a "jar-with-dependencies" into a module.

If you have the same package in 2 jar files, you need to fix that before declaring module names. This appears to be the case with okhttp and okhttp-urlconnection.

Subpackages don't exist in the JVM. Each package has a name - humans give them subpackage meaning, but the JVM does not.

Your module name should be the same as the package name in that jar file, unless you have a good reason otherwise. ie. you as a human are deciding that one package is the base, and assigning that as the module name. Thus the okhttp3 pom.xml would declare a module name of okhttp3 (I dislike that this is not com.squareup.okhttp3 but you should still match the package name)

I think using ${project.groupId} in the module name setup is unwise. The module name is just as much a part of your source code as the package name is, and should be treated as part of your API for compatibility purposes. Just encode the full name in the pom.xml so it doesn't get changed. In addition, Maven artifact and group IDs are often bad guidance for module names. Focus on the package names, and you'll be fine.

BTW, you can add a module-info.java file and still release a Java 8 jar file. See Joda-Collect for example. I know Android has had difficulties with module-info.class but that is something that is going to have to get solved ;-) Adding the module-info would allow the internal packages to be properly hidden, which is probably a good thing, but does require all dependencies to be modules.

@yschimke
Copy link
Collaborator Author

@jodastephen Am I correct that the current setup is strictly better than defaulting from JAR file names? i.e. is it worth landing something close to this, or deferring until a bigger rewrite for Java 9?

In which case, we could just agree the automatic name for okhttp-core and a few other usable libraries and ship this for now. OkHttp could be suitable for modularisation if clients only use core and not urlconnection.

Firstly, do not add a module-info.java module declaration until:

all of your runtime dependencies have been modularised (either as a full module or with a MANIFEST.MF entry)
all those modularised dependencies have been released to Maven Central
your library depends on the updated versions
Secondly, if you can't meet these criteria, but your project is well structured and otherwise suitable for modularisation, please add a MANIFEST.MF entry following the agreed module naming conventions (super-package reverse-DNS).

And that resolving overlap is most relevant when adding module-info.java files?

An automatic module is a normal jar file - one without a module-info.class file - that is placed on the modulepath. Thus the modulepath will contain two types of module - "real" and "automatic". Since there is no module-info.class, an automatic module is missing the metadata normally associated with a module:

no module name
no list of exported packages
no list of dependencies
Unsurprisingly, the list of exported packages is simply set to be all packages in the jar file. The list of dependencies is set to be everything on the modulepath, plus the whole classpath. As such, automatic modules allow the modulepath to depend on the classpath, something which is normally not allowed. While not ideal, both of these defaults for the metadata make sense.

The final missing piece of information is the module name. This has been a big point of discussion in Project Jigsaw. As it stands, the module name will be derived from the filename of the jar file. For me, this is a critical problem with the basic design of automatic modules (but see the mitigation section below).

@jodastephen
Copy link

It is best if the clashing packages should be resolved before including module names. If you don't, then users will have problems if one or both of the jar files is on the module-path. (The clashing package check does not occur if both are on the class-path, however Maven will put them on the module-path, because of the Automatic-Module-Name.

How hard is it to solve the clashing package...

@yschimke
Copy link
Collaborator Author

yschimke commented Feb 1, 2018

@jodastephen What I'm confused about is why this PR is worse than the current situation. At least this gives a stable name to a widely used library - OkHttp Core.

The current release already has automatic names, they are just mutable. See okhttp.urlcnxn, in the renamed jar file.

$ /Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/jar -f ~/Downloads/okhttp-3.9.1.jar -d
No module descriptor found. Derived automatic module.

okhttp@3.9.1 automatic
requires java.base mandated
contains okhttp3
contains okhttp3.internal
contains okhttp3.internal.cache
contains okhttp3.internal.cache2
contains okhttp3.internal.connection
contains okhttp3.internal.http
contains okhttp3.internal.http1
contains okhttp3.internal.http2
contains okhttp3.internal.io
contains okhttp3.internal.platform
contains okhttp3.internal.publicsuffix
contains okhttp3.internal.tls
contains okhttp3.internal.ws

$ /Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/jar -f ~/Downloads/okhttp-urlconnection-3.9.1.jar -d
No module descriptor found. Derived automatic module.

okhttp.urlconnection@3.9.1 automatic
requires java.base mandated
contains okhttp3
contains okhttp3.internal
contains okhttp3.internal.huc

$ cp ~/Downloads/okhttp-urlconnection-3.9.1.jar ~/Downloads/okhttp-urlcnxn-3.9.1.jar

$ /Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/jar -f ~/Downloads/okhttp-urlcnxn-3.9.1.jar -d
No module descriptor found. Derived automatic module.

okhttp.urlcnxn@3.9.1 automatic
requires java.base mandated
contains okhttp3
contains okhttp3.internal
contains okhttp3.internal.huc

Copy link
Collaborator

@swankjesse swankjesse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is right

<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>${project.groupId}.logginginterceptor</Automatic-Module-Name>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logginginterceptor –> logging ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use logging-interceptor in the module name but just logging in the package name

okcurl/pom.xml Outdated
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>${project.groupId}.okcurl</Automatic-Module-Name>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want curl here, to match the package name of okhttp3.curl

@swankjesse
Copy link
Collaborator

I think we want com.squareup.okhttp3, com.squareup.okhttp3.apache, etc. ?

@swankjesse
Copy link
Collaborator

Actually, lets keep this ’cause it’s consistent with our packages. I just merged the Okio one but I’ll change it to be okio only.

@swankjesse swankjesse merged commit d27531a into square:master Feb 4, 2018
@swankjesse
Copy link
Collaborator

square/okio#343

@yschimke
Copy link
Collaborator Author

yschimke commented Feb 4, 2018

Yeah, I took the recommendation above

Your module name should be the same as the package name in that jar file, unless you have a good reason otherwise. ie. you as a human are deciding that one package is the base, and assigning that as the module name. Thus the okhttp3 pom.xml would declare a module name of okhttp3 (I dislike that this is not com.squareup.okhttp3 but you should still match the package name)

I think using ${project.groupId} in the module name setup is unwise. The module name is just as much a part of your source code as the package name is, and should be treated as part of your API for compatibility purposes. Just encode the full name in the pom.xml so it doesn't get changed. In addition, Maven artifact and group IDs are often bad guidance for module names. Focus on the package names, and you'll be fine.

@jodastephen
Copy link

The module names in the merged PR look OK to me, although I'm still concerned by the clashing packages.

codefromthecrypt pushed a commit to openzipkin/zipkin that referenced this pull request Mar 2, 2018
This is the easy way out of getting module names stable and mapped to
our entrypoint packages. I've only done this for the highly re-used
jars.

See square/okhttp#3743
thx @yschimke
codefromthecrypt pushed a commit to openzipkin/zipkin that referenced this pull request Mar 2, 2018
This is the easy way out of getting module names stable and mapped to
our entrypoint packages. I've only done this for the highly re-used
jars.

See square/okhttp#3743
thx @yschimke
codefromthecrypt pushed a commit to openzipkin/zipkin-reporter-java that referenced this pull request Mar 3, 2018
This is the easy way out of getting module names stable and mapped to
our entrypoint packages. I've only done this for the highly re-used
jars.

See square/okhttp#3743
thx @yschimke
codefromthecrypt pushed a commit to openzipkin/brave that referenced this pull request Mar 3, 2018
This is the easy way out of getting module names stable and mapped to
our entrypoint packages. I've only done this for the highly re-used
jars.

See square/okhttp#3743
thx @yschimke
@yschimke yschimke deleted the module_names branch March 14, 2018 04:56
abesto pushed a commit to abesto/zipkin that referenced this pull request Sep 10, 2019
This is the easy way out of getting module names stable and mapped to
our entrypoint packages. I've only done this for the highly re-used
jars.

See square/okhttp#3743
thx @yschimke
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants