I'm working on a project which represents a Maven ...
# plugin-development
s
I'm working on a project which represents a Maven plugin. I am trying to build this plugin using Maven Embedder integrated into Gradle. It works, but I have a frustrating problem with logging I simply cannot figure out -
Copy code
The SLF4J binding actually used is not supported by Maven: org.gradle.internal.logging.slf4j.OutputEventListenerBackedLoggerContext
Maven supported bindings are:
(from jar:file:/home/sebersole/.gradle/caches/modules-2/files-2.1/org.apache.maven/maven-embedder/3.9.9/fb988b4e85cec2686e56da94769cbf73298ef3ee/maven-embedder-3.9.9.jar!/META-INF/maven/slf4j-configuration.properties)
- org.slf4j.impl.SimpleLoggerFactory
- org.slf4j.impl.MavenSimpleLoggerFactory
- ch.qos.logback.classic.LoggerContext
- org.apache.logging.slf4j.Log4jLoggerFactory
But I cannot figure out how to resolve this. I've replaced sysout and syserr for the embedder calls. And I tried adding a different slf4j binding in the dependencies. All with no luck. Here is the Gradle project:
Copy code
dependencies {
	implementation gradleApi()
	implementation "org.apache.maven:maven-embedder:3.9.9"
	implementation "org.apache.maven:maven-compat:3.9.9"
	implementation "org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18"
	implementation "org.apache.maven.resolver:maven-resolver-transport-http:1.9.18"
	implementation "org.slf4j:slf4j-reload4j:2.0.16"
}

gradlePlugin {
	plugins {
		register( "mavenEmbedder" ) {
			id = "maven-embedder"
			implementationClass = "org.hibernate.build.maven.embedder.MavenEmbedderPlugin"
		}
	}
}
I'm not sure where embedder is finding the Gradle OutputEventListenerBackedLoggerContext. Any ideas? Thanks!
To be clear, the Gradle project I pasted is a local Gradle plugin which integrates Maven Embedder.
v
Isn't that more a Maven question than a Gradle question? For some weird reason that library wants to control which SLF4J backend you are allowed to use which is exactly the opposite of what thin logging facades like SLF4J or log4j-api try to achieve. Libraries use the facade and the consumer of the library should be able to use any binding for that facade. Without any further information I'd classify that as pretty big design bug in that library.
s
The Gradle part of the question is where else Gradle does this. Adjusting System.out and System.err had no effect, so it clearly does something else.
Set a static variable somewhere maybe?
v
Nor sure how sout and serr are involved? It complains about a not supported SLF4J binding which is the Gradle one.
s
Gradle replaces Syste,.ut and System.err that either is the logging stuff or has reference to it (I forget and my working tree has moved on in attempts to fix this)
(sorry, laptop keyboard)
I would ask the folks who are responsible for Maven Embedder, but well, that's hard to find
v
Maybe in the end you just have to debug it to find out. Code is always the most accurate reference and doc. 😄
s
Apprently it is just part of the larger Maven whole. Waiting on my request for a Jira account to be approved
Yep, the nexus of the internals of 2 codebases I'm not familar with. Should be simple 😉
👌 1
Related to this question, is there a way for a plugin to get access to its Configuration(s)? I'm talking about the dependencies defined on the pllugin project.
I think not, but never hurts to ask 🙂
(fwiw I did find Gradle's role in this... it simply uses its own "shaded" slf4j )
v
Related to this question, is there a way for a plugin to get access to its Configuration(s)? I'm talking about the dependencies defined on the pllugin project.
I think not, but never hurts to ask
What exactly is the use-case, depending on that the answer might vary 🙂 If you for example just need some resource from some dependency jar, just use the usual resource access on class or class loader. If you mean to actually access the jars for example to use them for some external Java process / process isolation worker / ..., there are quite hacky ways, but you should not even think about doing so, as Gradle manipulates the byte-code of the classpath of Gradle logic to automatically recognize configuration cache input and if you use those instrumented jars outside of Gradle logic, it will fail to find classes put in by that instrumentation.
(fwiw I did find Gradle's role in this... it simply uses its own "shaded" slf4j )
Even it it does, that would be quite irrelevant. It provides an own SLF4J binding as I said. And that is exactly the expected thing to do as explained above. That someone that logs with SLF4J only supports certain bindings, that sounds like big bullshit.
s
What exactly is the use-case...
Maven Embedder accepts a Plexus "ClassWorld" which is a super complicated take on a ClassLoader. I am trying to build a ClassWorld that has just needed Maven dependencies. At the moment, because I do not supply that, Maven Embedder simply uses the current VClassLoader. The easiest way to do this would be to define this ClassLoader as a Gradle Configuration and use that to access the files ad build that ClassWorld. It would suck to have to define a named Configuration on the project using the plugin just to specify the Maven dependencies (which are logically part of the plugin)
v
You can of course not access the configurations of the plugin, the plugin at runtime can hardly access information from its build script. 😄 But you don't need to create a named configuration in the user-space. Sometimes this makes sense, like if you integrate with some tool like SpotBugs or similar, it can make sense to add a user-space configuration with default dependencies, so that the users of the plugin could also supply own dependencies, for example a different version or even some compatible fork. If you do not want this, you can create a detached configuration which then is a plugin implementation detail. It then also does not participate for example in things like dependency locking, or tries to "download all external files without executing all tasks" or similar things.
s
Its even more fun trying to do this as a BuildService 😄
And yes, I understand I cannot access the plugin's build script lol. But those are used to define class-paths (
implementation
for the plugin needs to be on its classpath when it executes)
Anyway, I'll play around with detached config. Its actually what I just started
The BuildService bit makes it challenging
v
Well, the classloader with all the dependencies you can simply get with
getClass().getClassLoader()
. But as I said, you are not supposed to use it out of Gradle infrastructure due to the instrumentation. No idea whether that applies in your case.
s
yeah, a simple
getClassLoader()
won't work unfortunately.
I'll play with ClassWorlds and detached Configuration, but I'll no longer be able to use a BuildService here 😞
BuildService limitations keep hitting me everytime I think I have a valid use case for them
v
Which limitations are you talking about?
s
Limits on the type of parameters usually
Like ideally, I'd simply pass that detached Configuration as a parameter, but that's not allowed
v
Almost, make the parameter a
ConfigurableFileCollection
and then do
from(theConfiguration)
on the parameter
At least from the top of my head 🙂
s
It seems this only gives acccess to top-level dependencies. I'll keep playing with it as its a little closer
v
Only if you configure transitive to be false, otherwise you should get the whole tree
s
Unfortuntely not
Its something with the combo of 1. ConfigurableFileCollection 2. from(...) 3. getFiles
v
Proof!
s
Perhaps the getFiles is the cul[prit, noit sure yet
lol
I'll clean this up a bit and push if you really want to see
But I am having to add top-level dependencies for each of the ones listed at https://maven.apache.org/ref/3.9.7/maven-embedder/dependencies.html
v
Copy code
abstract class MyService : BuildService<MyService.Parameters> {
    init {
        parameters.files.forEach { println(it.name) }
    }

    interface Parameters : BuildServiceParameters {
        val files: ConfigurableFileCollection
    }
}
val foo = configurations.dependencyScope("foo")
val bar = configurations.resolvable("bar") {
    extendsFrom(foo.get())
}
dependencies {
    foo("org.apache.maven:maven-embedder:3.9.7")
}
gradle.sharedServices.registerIfAbsent("my-service", MyService::class) {
    parameters {
        files.from(bar)
    }
}.get()
=>
Copy code
maven-embedder-3.9.7.jar
maven-core-3.9.7.jar
maven-settings-builder-3.9.7.jar
maven-settings-3.9.7.jar
maven-plugin-api-3.9.7.jar
maven-resolver-provider-3.9.7.jar
maven-model-builder-3.9.7.jar
maven-model-3.9.7.jar
maven-builder-support-3.9.7.jar
maven-resolver-impl-1.9.20.jar
maven-resolver-util-1.9.20.jar
maven-resolver-spi-1.9.20.jar
maven-resolver-api-1.9.20.jar
maven-shared-utils-3.4.2.jar
guice-5.1.0.jar
guava-33.2.0-jre.jar
failureaccess-1.0.2.jar
plexus-sec-dispatcher-2.0.jar
plexus-cipher-2.0.jar
javax.inject-1.jar
org.eclipse.sisu.plexus-0.9.0.M2.jar
javax.annotation-api-1.3.2.jar
maven-repository-metadata-3.9.7.jar
maven-artifact-3.9.7.jar
plexus-utils-3.5.1.jar
plexus-classworlds-2.8.0.jar
plexus-interpolation-1.27.jar
maven-resolver-named-locks-1.9.20.jar
slf4j-api-1.7.36.jar
commons-cli-1.7.0.jar
commons-lang3-3.14.0.jar
org.eclipse.sisu.inject-0.9.0.M2.jar
plexus-component-annotations-2.1.0.jar
aopalliance-1.0.jar
s
Yep, I get that too. But attempting to use a URLClassLoader built from those leads to inability to load classes from transitive deps. So 🤷🏼
Copy code
> Could not create an instance of type org.hibernate.build.maven.embedder.MavenEmbedderService.
         > org/apache/commons/cli/ParseException
Its complaining because org/apache/commons/cli/ParseException cannot be found
But as youy see, its in "the list"
v
It is in the list because the file is there and delivered.
s
lol
v
If it cannot be loaded it is probably a different problem?
s
We can keep arguing about what I plainly see here I guess
Well I mean clearly 😉
I just have nooooo clue what that is
v
What does the
--stacktrace
say? You did not really show the real error.
And what do you try to do, getting that error?
Adding in my example
Copy code
println(URLClassLoader(parameters.files.map { it.toURI().toURL() }.toTypedArray(), null).loadClass("org.apache.commons.cli.ParseException"))
=>
Copy code
class org.apache.commons.cli.ParseException
so worked
s
Copy code
Caused by: java.lang.NoClassDefFoundError: org/apache/maven/cli/MavenCli$ExitException
        at org.hibernate.build.maven.embedder.MavenEmbedderService.resolveEmbedderConstructor(MavenEmbedderService.java:133)
I am using this to delegate to Maven to generate descriptors for a Maven plugin
v
Concretly in code, not abstract
s
Initially it worked but the logging became problemantic which is when I asked this question
v
Yeah, what do you do right now to get that error
Copy code
println(URLClassLoader(parameters.files.map { it.toURI().toURL() }.toTypedArray(), null).loadClass("org.apache.maven.cli.MavenCli\$ExitException"))
also works fine
s
I'm forced to use "reflection programming" here, so keep that in mind. But roughly I have:
Copy code
final Class<?> delegateClass = loadDelegateClass( getParameters().getEmbedderDependencies() );
		this.embedderDelegate = new MavenEmbedderDelegate(
				getParameters().getWorkingDirectory().get().getAsFile(),
				getParameters().getMavenLocalDirectory().get().getAsFile(),
				delegateClass
		);
The problematic call is a call to use the constructor
Copy code
private static Class<?> loadDelegateClass(ConfigurableFileCollection embedderDependenciesCollection) {
		System.out.println( "################################################" );
		System.out.println( "`embedder` dependency files (from service) -" );
		for ( File file : embedderDependenciesCollection.getFiles() ) {
			System.out.println( "    - " + file.getName() + " (exists - " + file.exists() + ")" );
		}
		System.out.println( "################################################" );

		final URL[] urls = collectDependencyUrls( embedderDependenciesCollection );

		try (URLClassLoader urlClassLoader = new URLClassLoader( urls )) {
			return urlClassLoader.loadClass( EMBEDDER_CLASS_NAME );
		}
		catch (Exception e) {
			throw new RuntimeException( "Unable to load Maven Embedder class", e );
		}
	}

	private static URL @NotNull [] collectDependencyUrls(ConfigurableFileCollection embedderDependenciesCollection) {
		final Set<File> embedderDependencies = embedderDependenciesCollection.getFiles();
		final URL[] urls = new URL[embedderDependencies.size()];

		try {
			int position = 0;
			for ( File embedderDependency : embedderDependencies ) {
				urls[position++] = embedderDependency.toURL();
			}
		}
		catch (Exception e) {
			throw new RuntimeException( "Unable to process embedder dependencies for loading Maven Embedder class", e );
		}
		return urls;
	}
v
And btw. that I used named configuration is not the difference, this also works fine 🙂
Copy code
abstract class MyService : BuildService<MyService.Parameters> {
    init {
        parameters.files.forEach { println(it.name) }
        println()
        println(URLClassLoader(parameters.files.map { it.toURI().toURL() }.toTypedArray(), null).loadClass("org.apache.maven.cli.MavenCli\$ExitException"))
    }

    interface Parameters : BuildServiceParameters {
        val files: ConfigurableFileCollection
    }
}
gradle.sharedServices.registerIfAbsent("my-service", MyService::class) {
    parameters {
        files.from(configurations.detachedConfiguration(dependencies.create("org.apache.maven:maven-embedder:3.9.7")))
    }
}.get()
s
The sysout shows exactly what you showed as the list of files
But still, here I am
v
And
EMBEDDER_CLASS_NAME
is?
s
Copy code
public static final String EMBEDDER_CLASS_NAME = "org.apache.maven.cli.MavenCli";
v
Copy code
abstract class MyService : BuildService<MyService.Parameters> {
    init {
        parameters.files.forEach { println(it.name) }
        println()
        println(URLClassLoader(parameters.files.map { it.toURI().toURL() }.toTypedArray()).loadClass("org.apache.maven.cli.MavenCli"))
        println(loadDelegateClass(parameters.files))
    }

    interface Parameters : BuildServiceParameters {
        val files: ConfigurableFileCollection
    }

    private fun loadDelegateClass(embedderDependenciesCollection: ConfigurableFileCollection): Class<*> {
        println("################################################")
        println("`embedder` dependency files (from service) -")
        for (file in embedderDependenciesCollection.files) {
            println("    - ${file.name} (exists - ${file.exists()})")
        }
        println("################################################")

        val urls: Array<URL?>? = collectDependencyUrls(embedderDependenciesCollection)

        URLClassLoader(urls).use { urlClassLoader ->
            return urlClassLoader.loadClass("org.apache.maven.cli.MavenCli")
        }
    }

    private fun collectDependencyUrls(embedderDependenciesCollection: ConfigurableFileCollection): Array<URL?>? {
        val embedderDependencies = embedderDependenciesCollection.files
        val urls: Array<URL?> = arrayOfNulls<URL>(embedderDependencies.size)

        var position = 0
        for (embedderDependency in embedderDependencies) {
            urls[position++] = embedderDependency.toURI().toURL()
        }
        return urls
    }
}
gradle.sharedServices.registerIfAbsent("my-service", MyService::class) {
    parameters {
        files.from(configurations.detachedConfiguration(dependencies.create("org.apache.maven:maven-embedder:3.9.7")))
    }
}.get()
=>
Copy code
maven-embedder-3.9.7.jar
maven-core-3.9.7.jar
maven-settings-builder-3.9.7.jar
maven-settings-3.9.7.jar
maven-plugin-api-3.9.7.jar
maven-resolver-provider-3.9.7.jar
maven-model-builder-3.9.7.jar
maven-model-3.9.7.jar
maven-builder-support-3.9.7.jar
maven-resolver-impl-1.9.20.jar
maven-resolver-util-1.9.20.jar
maven-resolver-spi-1.9.20.jar
maven-resolver-api-1.9.20.jar
maven-shared-utils-3.4.2.jar
guice-5.1.0.jar
guava-33.2.0-jre.jar
failureaccess-1.0.2.jar
plexus-sec-dispatcher-2.0.jar
plexus-cipher-2.0.jar
javax.inject-1.jar
org.eclipse.sisu.plexus-0.9.0.M2.jar
javax.annotation-api-1.3.2.jar
maven-repository-metadata-3.9.7.jar
maven-artifact-3.9.7.jar
plexus-utils-3.5.1.jar
plexus-classworlds-2.8.0.jar
plexus-interpolation-1.27.jar
maven-resolver-named-locks-1.9.20.jar
slf4j-api-1.7.36.jar
commons-cli-1.7.0.jar
commons-lang3-3.14.0.jar
org.eclipse.sisu.inject-0.9.0.M2.jar
plexus-component-annotations-2.1.0.jar
aopalliance-1.0.jar

class org.apache.maven.cli.MavenCli
################################################
`embedder` dependency files (from service) -
    - maven-embedder-3.9.7.jar (exists - true)
    - maven-core-3.9.7.jar (exists - true)
    - maven-settings-builder-3.9.7.jar (exists - true)
    - maven-settings-3.9.7.jar (exists - true)
    - maven-plugin-api-3.9.7.jar (exists - true)
    - maven-resolver-provider-3.9.7.jar (exists - true)
    - maven-model-builder-3.9.7.jar (exists - true)
    - maven-model-3.9.7.jar (exists - true)
    - maven-builder-support-3.9.7.jar (exists - true)
    - maven-resolver-impl-1.9.20.jar (exists - true)
    - maven-resolver-util-1.9.20.jar (exists - true)
    - maven-resolver-spi-1.9.20.jar (exists - true)
    - maven-resolver-api-1.9.20.jar (exists - true)
    - maven-shared-utils-3.4.2.jar (exists - true)
    - guice-5.1.0.jar (exists - true)
    - guava-33.2.0-jre.jar (exists - true)
    - failureaccess-1.0.2.jar (exists - true)
    - plexus-sec-dispatcher-2.0.jar (exists - true)
    - plexus-cipher-2.0.jar (exists - true)
    - javax.inject-1.jar (exists - true)
    - org.eclipse.sisu.plexus-0.9.0.M2.jar (exists - true)
    - javax.annotation-api-1.3.2.jar (exists - true)
    - maven-repository-metadata-3.9.7.jar (exists - true)
    - maven-artifact-3.9.7.jar (exists - true)
    - plexus-utils-3.5.1.jar (exists - true)
    - plexus-classworlds-2.8.0.jar (exists - true)
    - plexus-interpolation-1.27.jar (exists - true)
    - maven-resolver-named-locks-1.9.20.jar (exists - true)
    - slf4j-api-1.7.36.jar (exists - true)
    - commons-cli-1.7.0.jar (exists - true)
    - commons-lang3-3.14.0.jar (exists - true)
    - org.eclipse.sisu.inject-0.9.0.M2.jar (exists - true)
    - plexus-component-annotations-2.1.0.jar (exists - true)
    - aopalliance-1.0.jar (exists - true)
################################################
class org.apache.maven.cli.MavenCli
v
Works fine here 🙂
s
Grr
v
Checked out your project, synced to IDE, worked with seeing the debug output, did
gw help
, output
Copy code
19:41:22: Executing 'help'...

> Task :local-build-plugins:extractPluginRequests UP-TO-DATE
> Task :local-build-plugins:generatePluginAdapters UP-TO-DATE
> Task :local-build-plugins:compileJava UP-TO-DATE
> Task :local-build-plugins:compileGroovy NO-SOURCE
> Task :local-build-plugins:compileGroovyPlugins UP-TO-DATE
> Task :local-build-plugins:pluginDescriptors UP-TO-DATE
> Task :local-build-plugins:processResources UP-TO-DATE
> Task :local-build-plugins:classes UP-TO-DATE
> Task :local-build-plugins:jar UP-TO-DATE

> Configure project :maven-plugin-testing-plugin
################################################
`embedder` dependency files -
    - maven-embedder-3.9.9.jar
    - maven-compat-3.9.9.jar
    - maven-resolver-connector-basic-1.9.18.jar
    - maven-resolver-transport-http-1.9.18.jar
    - maven-core-3.9.9.jar
    - maven-plugin-api-3.9.9.jar
    - maven-plugin-annotations-3.6.0.jar
    - maven-project-2.2.1.jar
    - slf4j-reload4j-2.0.16.jar
    - maven-shared-utils-3.4.2.jar
    - maven-resolver-provider-3.9.9.jar
    - maven-resolver-impl-1.9.22.jar
    - jcl-over-slf4j-1.7.36.jar
    - maven-resolver-named-locks-1.9.22.jar
    - slf4j-api-2.0.16.jar
    - maven-settings-builder-3.9.9.jar
    - maven-settings-3.9.9.jar
    - maven-model-builder-3.9.9.jar
    - maven-profile-2.2.1.jar
    - maven-model-3.9.9.jar
    - maven-builder-support-3.9.9.jar
    - maven-resolver-util-1.9.22.jar
    - maven-resolver-spi-1.9.22.jar
    - maven-resolver-api-1.9.22.jar
    - guice-5.1.0.jar
    - guava-33.2.1-jre.jar
    - failureaccess-1.0.2.jar
    - plexus-sec-dispatcher-2.0.jar
    - plexus-cipher-2.0.jar
    - javax.inject-1.jar
    - javax.annotation-api-1.3.2.jar
    - org.eclipse.sisu.plexus-0.9.0.M3.jar
    - maven-artifact-manager-2.2.1.jar
    - maven-artifact-3.9.9.jar
    - maven-repository-metadata-3.9.9.jar
    - wagon-provider-api-3.5.3.jar
    - maven-plugin-registry-2.2.1.jar
    - plexus-container-default-1.0-alpha-9-stable-1.jar
    - plexus-utils-3.5.1.jar
    - plexus-classworlds-2.8.0.jar
    - plexus-interpolation-1.27.jar
    - commons-cli-1.8.0.jar
    - plexus-component-annotations-2.1.0.jar
    - httpclient-4.5.14.jar
    - httpcore-4.4.16.jar
    - commons-codec-1.16.0.jar
    - reload4j-1.2.22.jar
    - org.eclipse.sisu.inject-0.9.0.M3.jar
    - aopalliance-1.0.jar
    - plexus-xml-3.0.0.jar
    - backport-util-concurrent-3.1.jar
    - junit-3.8.1.jar
    - classworlds-1.1-alpha-2.jar
################################################
################################################
`embedder` dependency files -
    - maven-embedder-3.9.9.jar
    - maven-compat-3.9.9.jar
    - maven-resolver-connector-basic-1.9.18.jar
    - maven-resolver-transport-http-1.9.18.jar
    - maven-core-3.9.9.jar
    - maven-plugin-api-3.9.9.jar
    - maven-plugin-annotations-3.6.0.jar
    - maven-project-2.2.1.jar
    - slf4j-reload4j-2.0.16.jar
    - maven-shared-utils-3.4.2.jar
    - maven-resolver-provider-3.9.9.jar
    - maven-resolver-impl-1.9.22.jar
    - jcl-over-slf4j-1.7.36.jar
    - maven-resolver-named-locks-1.9.22.jar
    - slf4j-api-2.0.16.jar
    - maven-settings-builder-3.9.9.jar
    - maven-settings-3.9.9.jar
    - maven-model-builder-3.9.9.jar
    - maven-profile-2.2.1.jar
    - maven-model-3.9.9.jar
    - maven-builder-support-3.9.9.jar
    - maven-resolver-util-1.9.22.jar
    - maven-resolver-spi-1.9.22.jar
    - maven-resolver-api-1.9.22.jar
    - guice-5.1.0.jar
    - guava-33.2.1-jre.jar
    - failureaccess-1.0.2.jar
    - plexus-sec-dispatcher-2.0.jar
    - plexus-cipher-2.0.jar
    - javax.inject-1.jar
    - javax.annotation-api-1.3.2.jar
    - org.eclipse.sisu.plexus-0.9.0.M3.jar
    - maven-artifact-manager-2.2.1.jar
    - maven-artifact-3.9.9.jar
    - maven-repository-metadata-3.9.9.jar
    - wagon-provider-api-3.5.3.jar
    - maven-plugin-registry-2.2.1.jar
    - plexus-container-default-1.0-alpha-9-stable-1.jar
    - plexus-utils-3.5.1.jar
    - plexus-classworlds-2.8.0.jar
    - plexus-interpolation-1.27.jar
    - commons-cli-1.8.0.jar
    - plexus-component-annotations-2.1.0.jar
    - httpclient-4.5.14.jar
    - httpcore-4.4.16.jar
    - commons-codec-1.16.0.jar
    - reload4j-1.2.22.jar
    - org.eclipse.sisu.inject-0.9.0.M3.jar
    - aopalliance-1.0.jar
    - plexus-xml-3.0.0.jar
    - backport-util-concurrent-3.1.jar
    - junit-3.8.1.jar
    - classworlds-1.1-alpha-2.jar
################################################

> Task :help

Welcome to Gradle 8.5.

To run a build, run gradle <task> ...

To see a list of available tasks, run gradle tasks

To see more detail about a task, run gradle help --task <task>

To see a list of command-line options, run gradle --help

For more detail on using Gradle, see <https://docs.gradle.org/8.5/userguide/command_line_interface.html>

For troubleshooting, visit <https://help.gradle.org>

BUILD SUCCESSFUL in 9s
8 actionable tasks: 1 executed, 7 up-to-date
19:41:32: Execution finished 'help'.
s
Could you try :
gradlew generatePluginDescritor
?
I'm not sure exactly whewn the service is created
v
Well, you see your debug output, so ...
But sure, one moment
s
No you're right
But I am unable to explain any of this so...
v
Actually, I right now wonder why you get it twice
s
I did it in multiple places
v
Task 'generatePluginDescritor' not found in root project 'maven-plugin-testing' and its subprojects. Some candidates are: 'generatePluginDescriptor'.
s
Gah, I mistyped. The laptop keyboard is killing me
v
Ah, ok you have it in three places, then it could be not from the service actually
Ah, yes, now I get the same error 🙂
So we are back to "this is not a Gradle question" 😄
You close the classloader after loading the embedder class. When you then try to get the constructor, you need additional classes, but the classloader is closed already, so they cannot be loaded.
If I simply move the classloader out of the try-with-resources I get an actual usage error from maven
So you probably should then close the classloader in the
close
method of the service with implementing
AutoCloseable
, so that the classloader is only closed once the service is discarded.
So half-way a Gradle question 😄
Btw. instead of using reflection, you could consider instead using the worker api with classloader isolation in your task. That might maybe be more idiomatic and convenient.
s
I've not played with the worker api yet, I'll take a look
Yeah, the reflection stuff sucked but I'm just not seeing another way to get Gradle off the classloader used
Gradle hard-codes the sl4fj factory to use, which is the thing that started me down this rabbit hole 🙂
v
Yeah, I hope(TM) the class-loader isolated worker will work, but I might as well be wrong 🙂
s
About to just make a system call lol
v
Nooooo 🙂
s
I get "further" using your AutoCloseable suggestion
👌 1
v
I was curious and gave the worker api a quick try. Does not work, the slf4j binding error comes, even with classloader isolation and process isolation. So yeah, you probably need the reflection fun when not forking away with
ExecOperations#javaExec
or similar.
👍🏼 1