1

I'm developing custom Maven plugin. I want my plugin to add a new dependency to a project.

I have the following code:

@Mojo(name = "generate-model", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
public class ModelGeneratorMojo extends AbstractMojo {
    @Parameter(defaultValue = "${project}", required = true, readonly = true)
    MavenProject project;

    @Override
    public void execute() throws MojoExecutionException {
        Dependency connectivity = new Dependency();
        connectivity.setGroupId("groupid");
        connectivity.setArtifactId("artifactid");
        connectivity.setVersion("1.0");
        //noinspection unchecked
        project.getDependencies().add(connectivity);
    }
}

It seems to have no effect, because when I compile a project containing this plugin, I get unresolved symbol error.

I'm sure that plugin is executed because I see code generated by it (code generation is omitted in my example) in target folder.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
talex
  • 17,973
  • 3
  • 29
  • 66
  • Can you paste the error that you get at least? – Yassin Hajaj Apr 12 '21 at 09:37
  • @YassinHajaj Exact error is `ERROR] /home/atcvetkov/project/segeraroot/quote-model/target/generated-sources/model/segeraroot/quotemodel/ReadersVisitor.java:[9,43] package segeraroot.connectivity does not exist`, but it is irrelevant because it isn't root cause of an issue. It happens because dependency isn't added to project as I expect. – talex Apr 12 '21 at 09:41
  • Have you bound the plugin to the right phase of build process? – Jahan Zinedine Apr 12 '21 at 09:49
  • What are trying to achieve with this? If you add a plugin to a POM that adds a dependency, then likely nothing will happen because the resolution of dependencies happens way before plugins are executed. – J Fabian Meier Apr 12 '21 at 10:06
  • @Jahan it currently bounded to `generate-sources`. Which phase is correct? – talex Apr 12 '21 at 10:09
  • I added an answer, check that out and see if it works – Jahan Zinedine Apr 12 '21 at 10:10
  • @JFabianMeier so it is impossible to add dependency from plugin? – talex Apr 12 '21 at 10:10
  • I guess so. What is the problem you want to solve? – J Fabian Meier Apr 12 '21 at 10:17
  • A plugin which add dependencies to a project is a bad idea... you can generate code etc. no problem but dependencies should be in the pom file and not auto magically added by. a plugin furthermore the question is: Why should a plugin add a dependency to a project? – khmarbaise Apr 12 '21 at 11:37
  • @khmarbaise "Why should a plugin add a dependency to a project?" to make life easier for people who will use it. – talex Apr 12 '21 at 12:02
  • @JFabianMeier i just wanted to make it easier to use. – talex Apr 12 '21 at 12:02
  • 1
    @talex In what sense? If your plugin needs something, you can add it as a dependency to the plugin. Why does a plugin need a dependency of the project? – J Fabian Meier Apr 12 '21 at 12:41
  • Adding a dependency to the project via a plugin is simply not possible because the dependencies are solved at a time where plugin has not been started...so changing the dependency tree afterwards would result (or must result) into a recalculation of the dependency tree (remove duplicate versions / clashes etc.) which is could result circular recalculations... furthermore where is it visible that a plugin adds a dependency... it is completely covered into the plugin...furthermore How could you handle updates of such a dependency? – khmarbaise Apr 12 '21 at 18:09
  • @talex I hate to be the "just don't do it" person after you gave a good reason for wanting to do it (usability), but is adding a dependency to a POM any harder than adding a plugin other than you need to paste two things from a doc instead of one? – Captain Man Apr 12 '21 at 21:39
  • @CaptainMan I finally dropped my idea. Even if it is possible it is too hard to implement. It wasn't important feature after all. I can live with two changes in pom instead of one. – talex Apr 14 '21 at 11:32

1 Answers1

1

I think you should bind the goal in your plugin to the Initialize phase of Maven build process to include the dependency very early in the build process.

Something along these lines:

@Mojo(name = "generate-model", defaultPhase = LifecyclePhase.INITIALIZE)
public class ModelGeneratorMojo extends AbstractMojo {
    @Parameter(defaultValue = "${project}", required = true, readonly = true)
    MavenProject project;

    @Parameter(defaultValue = "${session}", required = true)
    MavenSession session;


    @Override
    public void execute() throws MojoExecutionException {
        Dependency connectivity = new Dependency();
        connectivity.setGroupId("groupid");
        connectivity.setArtifactId("artifactid");
        connectivity.setVersion("1.0");

        project.getDependencies().add(connectivity);
        session.setCurrentProject(project);

    }
}
<plugin>
    <groupId>com.maventest</groupId>
    <artifactId>maven-generate-model</artifactId>
    <version>1.0-SNAPSHOT</version>
    <executions>
        <execution>
            <goals>
                <goal>generate-model</goal>
            </goals>
        </execution>
    </executions>
</plugin>

I tried multiple paths to accomplish this, but it seems not possible to do using maven plugins, probably maven extension is a better choice here.

The reason is that Depedency Resolution is the first step into Maven lifecycle and you need that extra dependency to compile the application. With maven extensions, you can extend the maven lifecycle. https://maven.apache.org/examples/maven-3-lifecycle-extensions.html

Jahan Zinedine
  • 14,616
  • 5
  • 46
  • 70
  • Unfortunately it didn't solved my problem. Same error occurs. – talex Apr 12 '21 at 10:14
  • Seems we need to add `session.setCurrentProject(project);` to make it work, I'll update you. – Jahan Zinedine Apr 12 '21 at 11:33
  • What is `session` and how to get it? – talex Apr 12 '21 at 12:00
  • You can inject it just like `project`, actually, I managed to get into the maven compiler plugin and now could confirm that the dependency is there, but still, compilation fails, I think because dependency download process happens earlier. – Jahan Zinedine Apr 12 '21 at 12:25
  • Turns out it's not straightforward to add a dependency so that maven resolve it before it runs a session as outlined here: https://stackoverflow.com/questions/28565091/how-to-get-a-maven-plugin-to-run-before-dependency-resolution – Jahan Zinedine Apr 12 '21 at 14:10