How to execute a specific plugin/Mojo from a pom.xml programmatically?
I'm the author of one of the Maven plugins (not Apache/Codehaus, completely indie). Sometimes I get support requests or test cases where I'd really need to debug the execution of my plugin with an existing pom.xml
. Basically the test cases I get are sample/test project ( pom.xml
with src/main/resoures
, src/main/java
and so on).
What I need is a way to:
pom.xml
. MyMojo
- fully initialized/condigured, with all the components and parameters corectly injected. MyMojo
. By debugging I mean to be able to set and halt on breakpoints (also conditional), step in/out/over on the source code.
Ideally I'd like to be able to executeMyMojoFrom(new File("pom.xml"))
- for instance in a JUnit test or a main
method of some class. (I can supply groupId
, artifactId
etc. All other definitions should just be loaded from that pom.xml
.)
How can I achieve this?
What I've tried so far:
Debug As...
on pom.xml
in Eclipse - does not work well enough (source code not found, breakpoint don't work as its not a Java project context) mvnDebug
and then remote debugging from Eclipse as suggested by Pascal Thivent here. This is so far the best option. However, remote debugging means starting mvnDebug
separately, and there's also not guarantee that the JARs I have in Eclipse are exactly the same that mvnDebug
is using. So there's a certain distance here. maven-plugin-testing-harness
- I actually thought this this will do the task. But first I was jumping through hoops for a few hours just to make it start. All of the important dependencies are "provided" so I first had to figure out the right combination of versions of these artifacts. And then - only to discover that AbstractMojoTestCase
only works within the plugin module you want to test. Probably I was mistaken when I thought that maven-plugin-testing-harness
was a testing harness for Maven plugins. It seems that it's a testing harness for the plugin from that plugin's module. Which is not illogical but does not help my case. I'd like to test my plugin in other modules. So right now I've got the best results with the remote debugging solution. But what I'm looking for is really something like maven-plugin-testing-harness
but not hardwired to the plugin module. Does anyone happen to have a hint, if such a method exists somewhere in Maven artifacts?
To be even more specific, I'd like to write something like:
public void testSomething()
throws Exception
{
File pom = getTestFile( "pom.xml" );
assertNotNull( pom );
assertTrue( pom.exists() );
MyMojo myMojo = (MyMojo) lookupMojo( "myGroupId", "myArtifactid", ...,
"myGoal", pom );
assertNotNull( myMojo );
myMojo.execute();
...
}
Compare it to the MyMojoTest
here - it's almost there. Should just not be hardwired into the mymojo
Maven module (as it is in maven-plugin-testing-harness
).
Update
Few answers to the questions in comments:
You mean you don't want such a test class, ie MyMojoTest
to reside inside the same project as the MyMojo
, ie your plugin project? Why is that?
Exactly. I want to debug the plugin execution in an existing Maven project, I don't want to move that project to my plugin project first to be able to run a test. I want to be able to test/debug an existing project. Ideally, I'd just need to add my-maven-plugin-testing
dependency and subclass MyMojoTest
in the project's src/test/jaca. This would be a good instrument to debug executions. Dragging the target project into my Mojo project ist just too much overhead - and mostly these aren't really the test cases I want to keep long-term. I hope, this answers, why.
Anyway, it's merely a convention to keep the project-to-test/pom.xml
inside the src/test/resources
of your plugin module, not a rule...
My problem is not the location of the pom.xml
of the project-to-test
, that is easily configurable. My difficulty is that maven-plugin-testing-harness
is is somehow hardcoded to be in the Mojo's project. It uses the pom.xml
of the Mojo, looks for other special files/descriptors in the containing project. So I somehow can't use it in a non-Mojo project, or can I? This is my question.
And I'm not sure why Debug as...
didn't help you...
Not sure either, but (1) breakpoints did not work and (2) the source code was not "attached" for some reason.
If the Debug as
didn't work for you as well as it should, you can try to use the mojo-executor
with a bit of work.
https://github.com/TimMoore/mojo-executor
This is how you would execute the copy-dependencies
goal of the Maven Dependency Plugin
programmatically:
executeMojo(
plugin(
groupId("org.apache.maven.plugins"),
artifactId("maven-dependency-plugin"),
version("2.0")
),
goal("copy-dependencies"),
configuration(
element(name("outputDirectory"), "${project.build.directory}/foo")
),
executionEnvironment(
mavenProject,
mavenSession,
pluginManager
)
);
The project
, session
, and pluginManager
variables should be injected via the normal Mojo injection. Yes, that means this should be executed from the context of another maven plugin. Now that I think about it, whether this would help you in any way is still a question because this still relies on injection of such components by the underlying plexus
container.
My original idea was though to have you build a maven plugin that would invoke your jaxb2
plugin thru the mojo-executor
like above, then serialize the mavenProject
, mavenSession
, pluginManager
, ie, all the plexus
injected components and then use those objects to invoke your jaxb2
plugin in future from a standalone class without the plugin that you built.