mavenmaven-compiler-plugin

In what Maven phase/goal of the default lifecycle do my remote pom dependencies get pulled down?


I've been struggling to understand what phase of the default lifecycle actually pulls down my remote dependencies in my pom.xml to my local .m2 folder.

It's my understanding that mvn dependency:resolve uses the maven dependency plugin to pull down any needed remote dependencies. According to this documentation it's supposed to be bound to the generate-sources phase.

However, if I run mvn generate-sources, maven doesn't seem to run the dependency resolution.

I suppose this is because the maven dependency plugin does not run by default unless explicitly specified in my pom?

In any case, I seem to only be able to hit this resolve step if I run mvn compile which shows my remote dependencies being pulled down in some kind of pre-step that gets placed before the resources plugin and compiler plugin run.

ā””[~/IdeaProjects/youtube-spring-reactive-programming]> mvn compile
[INFO] Scanning for projects...
[INFO] 
[INFO] ---------------< com.javatechie:springboot-webflux-demo >---------------
[INFO] Building springboot-webflux-demo 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from central: https://repo.maven.apache.org/maven2/org/projectlombok/lombok/1.18.22/lombok-1.18.22.pom
Downloaded from central: https://repo.maven.apache.org/maven2/org/projectlombok/lombok/1.18.22/lombok-1.18.22.pom (1.5 kB at 6.1 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/org/projectlombok/lombok/1.18.22/lombok-1.18.22.jar
Downloaded from central: https://repo.maven.apache.org/maven2/org/projectlombok/lombok/1.18.22/lombok-1.18.22.jar (2.0 MB at 12 MB/s)
[INFO] 
[INFO] --- maven-resources-plugin:3.3.1:resources (default-resources) @ springboot-webflux-demo ---
[INFO] Copying 1 resource from src/main/resources to target/classes
[INFO] Copying 0 resource from src/main/resources to target/classes
[INFO] 
[INFO] --- maven-compiler-plugin:3.11.0:compile (default-compile) @ springboot-webflux-demo ---
[INFO] Changes detected - recompiling the module! :dependency
[INFO] Compiling 1 source file with javac [debug release 17] to target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.313 s
[INFO] Finished at: 2023-10-28T12:32:31-07:00
[INFO] ------------------------------------------------------------------------

If I manually walk through each phase I don't ever get the remote dependencies pulled down until I hit the compile phase:

validate
initialize
generate-sources
process-sources
generate-resources
process-resources
compile   <--

I couldn't seem to find any granular documentation on what mvn compile is actually doing.

Question:

What is unique about the compile phase that kicks off this dependency resolution pre-step that appears to live outside of phases and the greater life cycle?


Solution

  • Executing mvn dependency:resolve in the end will execute maven-dependency-plugin or more accurate its executing the resolve goal of the plugin manually (https://maven.apache.org/plugins/maven-dependency-plugin/resolve-mojo.html) without starting the life-cycle.

    Second Maven itself does not use the maven-dependency-plugin to reolve dependendies (or download them). That is done by Maven itself (accurately by the resolver; not that important at the moment).

    The existing binding for the lifecycle and the plugins is linked in the appropriate description.

    Now coming to the dependency resolution (download of the artifacts).

    If you think about the different phases with the bound plugins like maven-resources-plugin, maven-compiler-plugin etc. to run the maven-resources-plugin is not required to download artifacts(execept the plugin itself and its dependencies), but as you already realized for running the maven-compiler-plugin the dependencies have to be downloaded (which results into to being put on the classpath) upfront before it can compile the code.

    There are markers (attributes of the annotation) in the plugins which tells the core if it's required to resolve the dependencies before the plugin will be called.

    In the maven-compiler-plugin source code shows something like this:

    @Mojo(
            name = "compile",
            defaultPhase = LifecyclePhase.COMPILE,
            threadSafe = true,
            requiresDependencyResolution = ResolutionScope.COMPILE)
    public class CompilerMojo extends AbstractCompilerMojo {
        /**
    

    The important part is the line requiresDependencyResolution = ResolutionScope.COMPILE. This is responsible to tell the core to resolve the dependencies before the plugin itself is being executed.

    If you look into the maven-compiler-plugin but now to the testCompile goal instead, the code looks like this:

    @Mojo(
            name = "testCompile",
            defaultPhase = LifecyclePhase.TEST_COMPILE,
            threadSafe = true,
            requiresDependencyResolution = ResolutionScope.TEST)
    public class TestCompilerMojo extends AbstractCompilerMojo {
    

    The line here: requiresDependencyResolution = ResolutionScope.TEST is telling the core to resolve all dependencies in scope test(to compile the test code).

    • Requires a Maven project to be executed.
    • Requires dependency resolution of artifacts in scope: compile.
    • The goal is thread-safe and supports parallel builds.
    • Since version: 2.0.
    • Binds by default to the lifecycle phase: compile.

    The line Requires dependency resolution of artifacts in scope: compile. is the equivalent of previous shown part from source code (The documentation page is generated from the source code).

    So based on the life-cycle phase compile which binds the compile goal of the Maven Compiler Plugin to it (as mentioned for the bindings).

    Accurately, is not the lifecycle the responsible part, it's the plugin goal which tells the core to resolve the dependencies before calling the plugin goal itself.