maven-plugin-development
maven-plugin-development copied to clipboard
Accessing "META-INF/maven/plugin.xml" files during tests
If I got this right, a maven plugin is nothing more than a regular jar with some additional metadata files in META-INF/maven/.
A jar built with the de.benediktritter.maven-plugin-development contains those file:
Screenshot of a jar corresponding to the example-maven-plugin project.
The files are generated in the $buildDir/mavenPlugin/descriptor folder.
Usually when I have a task that generates files that needs to be present in the jar, I modify the source set to add the generated folder like this:
sourceSets.main.output.dir file("$buildDir/mavenPlugin/descriptor"), builtBy: generateMavenPluginDescriptor
While I was working on having functional tests for my maven plugin (see https://github.com/britter/maven-plugin-development/issues/41 - I will share the results soon) I noticed that the META-INF/maven/plugin.xml are not available during the test.
Adding this code to a test shows the problem:
System.out.println(getClass().getClassLoader());
if (getClass().getClassLoader() instanceof URLClassLoader) {
Arrays.stream(((URLClassLoader) getClass().getClassLoader()).getURLs())
.forEach(e -> System.out.println(e));
} else {
System.out.println("XXXX Not a URLClassLoader");
}
During the test task the jar is not present on the classpath, only the folder containing the *.class files.
Output:
sun.misc.Launcher$AppClassLoader@2a139a55
file:/<user home>/.gradle/caches/7.3/workerMain/gradle-worker.jar
file:/<path to>/example-maven-plugin/build/classes/java/test/
file:/<path to>/example-maven-plugin/build/classes/java/main/
...
file:/<user home>/.gradle/caches/modules-2/files-2.1/junit/junit/4.12/2973d150c0dc1fefe998f834810d68f278ea58ec/junit-4.12.jar
... and a lot of other jars from the gradle cache (corresponding to my test runtime classpath)
I was wondering if this is intended?
Hey @jmini thank you for the report. I remember trying to do this but but there is a fundamental issue here that I'm not sure how to work around: The Maven plugin tools need to consume both the source files (to scan JavaDoc) and the compiled classes (to find annotations). For that reason the generate task consumes both the sources and the sourceset output as an inputs. Because of that it can not add something to the sourceset because that would result in a cycle. I can review this again and try to work around it, but I'm not sure it's possible.
As a workaround I think it should be possible to make the test tasks consume the jar instead of the classes folder. I can't tell how to do that from the top of my head, but I think it should be possible.
As a workaround I think it should be possible to make the test tasks consume the jar instead of the classes folder.
This would be great. I have a dependency to the jar task anyway. Because for functional tests, Maven (through the takari code) needs to know all the jars and all the pom files of the projects under test.
Currently my workaround is to add $buildDir/mavenPlugin/descriptor to the test source set.
It is wired, but working since once in the classpath it does not matters how it was added.
Following code has to find the MOJO xml file:
Enumeration<URL> resources = getClass().getClassLoader().getResources("META-INF/maven/plugin.xml");
Source in Maven30xRuntime.java
Otherwise the tests are failing with:
java.lang.AssertionError: The MojoDescriptor for the goal <name> cannot be null.
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.assertTrue(Assert.java:41)
at org.junit.Assert.assertNotNull(Assert.java:712)
at io.takari.maven.testing.Maven30xRuntime.newMojoExecution(Maven30xRuntime.java:234)
at io.takari.maven.testing.TestMavenRuntime.newMojoExecution(TestMavenRuntime.java:234)
at io.takari.maven.testing.TestMavenRuntime.executeMojo(TestMavenRuntime.java:244)
at io.takari.maven.testing.TestMavenRuntime.executeMojo(TestMavenRuntime.java:240)
If I can't make this work by adding it to the source set I think it's possible to add it to the testRuntimeClasspath from my plugin. I will look into it after I'm done with #73.