[ 
https://issues.apache.org/jira/browse/MNG-6906?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17719869#comment-17719869
 ] 

Tamas Cservenak commented on MNG-6906:
--------------------------------------

The understanding is correct, what the problem is that core extension is 
isolated from other core extension.

For more see here: [http://takari.io/book/91-maven-classloading.html]

And some here as well: 
[https://maven.apache.org/guides/mini/guide-using-extensions.html]

In short, lib/ext (and -Dmaven.ext.class.path as they are synonymous) work as 
they put extension in "maven core" classloader (is along with everything else 
in Maven Core in same classloader, does not have "own" classloader).

The .mvn/extensions.xml bit on the other hand creates separate "maven core 
extension" classloaders (each extension have one of its own) and they are core 
child and API imports them, hence E1 "cannot see" E2 due this.

Have to note that .mvn/extensions.xml is "late extension".

So, lib/ext should just work, while a possibly solution for .mvn/extensions.xml 
would be to create "meta" extension artifact that actually depends on two 
extension artifacts, that would result in both extensions landing in one 
classloader.

> Whether a core extension can access classes exported by another core 
> extension should not depend on how it is registered
> ------------------------------------------------------------------------------------------------------------------------
>
>                 Key: MNG-6906
>                 URL: https://issues.apache.org/jira/browse/MNG-6906
>             Project: Maven
>          Issue Type: Bug
>          Components: Class Loading
>            Reporter: Marc Philipp
>            Priority: Major
>
> 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}}:
> {code}
> <?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>
> {code}
> 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:
> {code}
> BuildScanApi buildScan = (BuildScanApi) 
> session.lookup("com.gradle.maven.extension.api.scan.BuildScanApi");
> {code}
> 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}}|(x) 
> {{NoClassDefFoundError}}|
> |{{.mvn/extensions.xml}}|{{.mvn/extensions.xml}}|(x) {{NoClassDefFoundError}}|
> |{{-Dmaven.ext.class.path}}|{{.mvn/extensions.xml}}|(/)|
> |{{<maven-home>/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:
> {code}
> 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);
>       }
>     });
> }
> {code}
> 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.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to