apache / apache/maven

[MNG-6906] Whether a core extension can access classes exported by another core extension should not depend on how it is registered

Open
#8,412 2 comments 0 reactions 0 assignees View on GitHub
bug priority:major
Dominant language
Java
Stars
5.3k
Forks
3.1k
Avg merge
20h 42m
Merged PRs (30d)
297

Description

**[Marc Philipp](https://issues.apache.org/jira/secure/ViewProfile.jspa?name=marcphilipp)** opened **[MNG-6906](https://issues.apache.org/jira/browse/MNG-6906?redirect=false)** and commented

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`:

```


com.gradle.maven.extension.api.scan
com.gradle.maven.mojo


com.gradle:gradle-enterprise-maven-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: `/lib/ext`, `-Dmaven.ext.class.path`, and `.mvn/extensions.xml`.

|consuming-extension|gradle-enterprise-maven-extension|Result|
|:---|:---|:---|
|`/lib/ext`|`/lib/ext`|(/)|
|`.mvn/extensions.xml`|`/lib/ext`|(/)|
|`-Dmaven.ext.class.path`|`/lib/ext`|(/)|
|`/lib/ext`|`.mvn/extensions.xml`|(x) `NoClassDefFoundError`|
|`.mvn/extensions.xml`|`.mvn/extensions.xml`|(x) `NoClassDefFoundError`|
|`-Dmaven.ext.class.path`|`.mvn/extensions.xml`|(/)|
|`/lib/ext`|`-Dmaven.ext.class.path`|(x) `NoClassDefFoundError`|
|`.mvn/extensions.xml`|`-Dmaven.ext.class.path`|(x) `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.

---

1 votes, 3 watchers

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.