When Maven executes phase or goal or lifecycle? - maven

When I was reading about Maven goals, phases on Stack Overflow, I came across two links in which one says:
when you execute maven you can specify a goal or a phase.
– What is the difference/relation between maven goals and phases?
and the other says:
You can't call the life-cycle-phase itself but you can call the goals of the plugins which are bound to the life-cycle-phases.
– Executing a specific Maven phase
Which one is right? Or am I not understanding it?
Also can some give me simple examples Maven executing lifecycle/phase/goal.
And also Maven knows that it has to run phase or a goal? E.g. when I say mvn install, is it install phase or goal?

Bombya Bo,
Think of Maven build life cycle like a fancy meal which has sequential phases:
starter (resources)
main (compile)
dessert (package)
coffee (install)
digestif (deploy)
A goal is the actual food being served during that phase.
starter: gazpacho
main: steak; gravy; fries
dessert: tiramisu
coffee: cappuccino
In this analogy:
pom.xml file is the equivalent of today's menu written on the chalk board
calling mvn on the command line is the equivalent of placing your order to the waiter
you can have more than one item of food/goal bound to a single phase (steak+gravy+fries)
If you like the house defaults, then you can just order the first N courses off the fixed menu:
"I'll take the 2 course meal"
$ mvn compile
You'll get everything up to and including the main course (ie gazpacho followed by steak+gravy+fries).
Calling a single goal is the equivalent of ordering a la carte:
"I'll take a Cobb salad plus the 2 course meal"
$ mvn javadoc:javadoc compile
If you want that goal to become a permanent addition to the menu, then add it to the pom file. That brings us back to calling:
$ mvn compile
which results in gazpacho+Cobb, followed by steak+gravy+fries.
A last point about binding a goal to a phase.
By default, each goal will run during a certain phase (Cobb salad usually served as a starter).
But you can override the phase binding, which is like telling the waiter "I'll have a Cobb salad, but bring it at the same time as the main"
Hope this clarifies the intuition behind goals vs. phases.

When you invoke a single plugin, you need to invoke a goal of that plugin. Like
mvn dependency:tree
in this case you are invoking the goal tree of the dependency plugin
On the other hand, you can invoke a phase of maven by simply doing
mvn test
In this case you are invoking not a plugin but a phase. Note that plugin goals can be bound to specific phases as well. The difference is whether you invoke the full phase (and all the preceding phases implicitly) or just a single goal of a single plugin
Here you can find all the phases of the default lifecycle (which can be modified, but i don't think you need to know about that for now), so as you can see, install is a phase

Related

Maven run plugin goal and preceding phases

Usually when we run a plugin goal in maven directly from the command line, the build phases preceding the one the plugin goal is bound to will not be run.
How can we run the plugin goal and all its preceding build phases?
There is no special support for this. But you can call
mvn preceding-phase goal:you-want-to-call
which will be essentially what you want.

Actual commands executed by Maven in a phase or goal

This is probably a question on Maven internals, and I haven't had much luck searching and finding the answer. Concisely, I'm interested in seeing what commands Maven actually execute for each phase or goal. For example, mvn package creates the jar file, so I'd think it must call the jar -cf command at some point.
Maven is opinionated so by design, this command doesn't show up in the .pom file. But which commands does Maven actually run for a specific phase and goal? Is there a way to see them?
The call creating a jar file is done in the maven-jar-plugin which is bound to the life cycle. You can do a mvn -X clean package to what happens behind the scenes. But you won't see many commands (except for javac compiling)... What do you mean by: Maven is opinionated so by design, this command doesn't show up in the .pom file?
The life cycles shows what kind of phases run bindings shows which plugins runs in which phase.
If you want to take a look into the sources of plugins all plugins can be found here: https://maven.apache.org/plugins/
On the right side you can see links to the appropriate version control system with links to it.
Each plugin has a link to the source code for example maven-jar-plugin: https://maven.apache.org/plugins/maven-jar-plugin/source-repository.html
Run mvn with the -X parameter, then look for lines starting with "[DEBUG] Executing command line:".
All the plugins are written in Java (or JVM-based languages), so if you can read it - you can find out what it does. Here are for example sources of the maven-jar-plugin: link1, link2.
But to get there you need to figure out which plugins and goals are executed when you run a phase. There are multiple ways:
In the output Maven says which goals it executes, example:
maven-resources-plugin:2.6:resources (default-resources) # module-name
If you generate an Effective POM, you'll be able to see all the plugins and which phases they are bound to: mvn help:effective-pom. Some plugins have default phases so people don't have to specify them explicitly - for these you'd have to look into the plugin meta information or into the sources.
Default plugins and goals are defined by the packaging. For the default packagings you could look into default-bindings.xml (role-hint is the packaging name).
After you know which plugins and goals are executed you can check out the sources of each plugin (the sources are usually open) and see its Mojos for the actual source code.
If you decide to learn the code it would be useful to be able to debug it when you run a mvn command. For that you can use mvnDebug instead of mvn.
More info: click1, click2.

Is there a way to simplify this maven command for sonar?

I'm running the following sonar command with maven:
mvn clean compile sonar:sonar
I'd like to just run:
mvn sonar:sonar
(ie have the sonar task trigger the clean and compile steps)
Is there a way to express this as a dependency in maven?
Quick Answer: No - not by declaring dependencies nor by having the plugin be in charge of the lifecycles and their phases to be run prior to the plugin's goal.
By mvn clean compile sonar:sonar you are instructing Maven to first run the entire clean-lifecycle with all its phases - then continoue with the default lifecycle to the phase compile and finally to call the goal sonar of the plugin sonar - i personally think the command is relativly short for what is going on and must not be simplified any further (what would be the actual benefit of a shorter command executing the same phases/ goals in the background?).
You can however bind plugins to certain build phases so that if the phase is run (say the phase process-classes right after phase compile in the default lifecycle) the plugin's goal will be executed automaticially.
This would abstract the need of explicitly calling sonar:sonar and allow for example to just call mvn clean process-classes and have sonar:sonar beeing executed in the process-classes phase of the default lifecycle.
Now to come back to your question one could generally ask if a Maven plugin can take controll of the lifecycles and phases beeing executed prior to its own goal which is as faar as i know not possible with "standard Maven techniques" (I however dont know of the possibilities if you write your own plugin).

Avoiding circular dependencies between Maven plugin build and test

I have a project with the following subprojects:
foo-codegen
...which, as the name implies, performs code generation...
foo-maven-plugin
...which invokes foo-codegen during the build process.
Generally speaking, this works fine. The problem, though, is when I want to test foo-codegen: foo-maven-plugin isn't yet available during foo-codegen's build cycle if we're putting things together in dependency order, but the build process for the tests invokes that plugin to actually perform the necessary code generation.
What's the right way to break this chain? Should I move foo-codegen's tests into a third subproject? Use the Maven Invoker plugin rather than foo-maven-plugin for doing code generation during the test phase? Something else?
If you do a mvn install or mvn deploy to a repository on the plugin first, then you can run them any order and do a mvn compile separately.

Difference between Maven source plugin jar and jar-no-fork goal?

Could you give me a detail explanation about the difference between jar and jar-no-fork goal?
I see it from official site, but I can not get a clear idea for this.
My interpretation: the jar goal is meant to be run from the command line (mvn source:jar), the jar-no-fork is meant to be bound to the lifecycle.
If you look at the docs for the jar goal the key phrase is "Invokes the execution of the lifecycle phase generate-sources prior to executing itself." If you configure your POM to run the source:jar goal as part of the lifecycle, Maven will re-run all of the goals bound to generate-sources and its predecessors. If you have many plugin goals bound to the validate or initialize phases all of those will run twice, lengthening the time of your build.
In contrast, jar-no-fork is what you attach to the build lifecycle because it expects to be bound to a phase somewhere after generate-sources and will not run the bound goals again.
I have verified this behavior by running Maven 3 with -X and reviewing the plugin executions that run.

Resources