Uploaded image for project: 'Maven'
  1. Maven
  2. MNG-6906

Whether a core extension can access classes exported by another core extension should not depend on how it is registered

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • None
    • None
    • Class Loading
    • None

    Description

      We have a Maven core extension (https://search.maven.org/artifact/com.gradle/gradle-enterprise-maven-extension/1.5/jar) that declares two packages as exported in its META-INF/maven/extension.xml:

      <?xml version="1.0" encoding="UTF-8"?>
      <extension>
        <exportedPackages>
          <exportedPackage>com.gradle.maven.extension.api.scan</exportedPackage>
          <exportedPackage>com.gradle.maven.mojo</exportedPackage>
        </exportedPackages>
        <exportedArtifacts>
          <exportedArtifact>com.gradle:gradle-enterprise-maven-extension</exportedArtifact>
        </exportedArtifacts>
      </extension>
      

      The first package (com.gradle.maven.extension.api.scan) contains a BuildScanApi interface for which the extension registers a component in an EventSpy at runtime.

      We would now like to consume that component in another core extension (let's call it consuming-extension) that has a provided dependency to com.gradle:gradle-enterprise-maven-extension like this:

      BuildScanApi buildScan = (BuildScanApi) session.lookup("com.gradle.maven.extension.api.scan.BuildScanApi");
      

      However, whether that works depends on how the core extensions are registered. Relevant for us are the following registration locations: <maven-home>/lib/ext, -Dmaven.ext.class.path, and .mvn/extensions.xml.

      consuming-extension gradle-enterprise-maven-extension Result
      <maven-home>/lib/ext <maven-home>/lib/ext
      .mvn/extensions.xml <maven-home>/lib/ext
      -Dmaven.ext.class.path <maven-home>/lib/ext
      <maven-home>/lib/ext .mvn/extensions.xml NoClassDefFoundError
      .mvn/extensions.xml .mvn/extensions.xml NoClassDefFoundError
      -Dmaven.ext.class.path .mvn/extensions.xml
      <maven-home>/lib/ext -Dmaven.ext.class.path NoClassDefFoundError
      .mvn/extensions.xml -Dmaven.ext.class.path NoClassDefFoundError
      -Dmaven.ext.class.path -Dmaven.ext.class.path

      With this workaround, I was able to get it working in all cases:

      ClassRealm extensionRealm = (ClassRealm) this.getClass().getClassLoader();
      if (!"maven.ext".equals(extensionRealm.getId())) {
        extensionRealm.getWorld().getRealms().stream()
          .filter(realm -> realm.getId().startsWith("coreExtension>com.gradle:gradle-enterprise-maven-extension:") || realm.getId().equals("maven.ext"))
          .max(comparing((ClassRealm realm) -> realm.getId().length()))
          .ifPresent(realm -> {
            try {
              extensionRealm.importFrom(realm.getId(), "com.gradle.maven.extension.api.scan");
            } catch (Exception e) {
              throw new RuntimeException("Could not import package from realm", e);
            }
          });
      }
      

      Please let me know if I have misunderstood the intention of declaring exported packages in extension.xml. I was unable to find documentation on it, unfortunately.

      Attachments

        Activity

          People

            Unassigned Unassigned
            marcphilipp Marc Philipp
            Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated: