What is the difference/relation between Maven goals and phases? How they are related to each other?
Goals are executed in phases which help determine the order goals get executed in. The best understanding of this is to look at the default Maven lifecycle bindings which shows which goals get run in which phases by default. The compile phase goals will always be executed before the test phase goals, which will always be executed before the package phase goals and so on.
Part of the confusion is exacerbated by the fact that when you execute Maven you can specify a goal or a phase. If you specify a phase then Maven will run all phases up to the phase you specified in order (e.g. if you specify package it will first run through the compile phase and then the test phase and finally the package phase) and for each phase it will run all goals attached to that phase.
When you create a plugin execution in your Maven build file and you only specify the goal then it will bind that goal to a given default phase. For example, the jaxb:xjc goal binds by default to the generate-resources phase. However, when you specify the execution you can also explicitly specify the phase for that goal as well.
If you specify a goal when you execute Maven then it will run that goal and only that goal. In other words, if you specify the jar:jar goal it will only run the jar:jar goal to package your code into a jar. If you have not previously run the compile goal or prepared your compiled code in some other way this may very likely fail.
Life cycle is a sequence of named phases.
Phases executes sequentially. Executing a phase means executes all previous phases.
Plugin is a collection of goals(i.e. tasks) which also called MOJO (Maven Old Java Object).
Maven is based around the central concept of a Build Life Cycles. Inside each Build Life Cycles there are Build Phases, and inside each Build Phases there are Build Goals.
We can execute either a build phase or build goal. When executing a build phase we execute all build goals within that build phase. Build goals are assigned to one or more build phases. We can also execute a build goal directly.
There are three major built-in Build Life Cycles:
default
clean
site
Each Build Lifecycle is Made Up of Phases
For example the default lifecycle comprises of the following Build Phases:
◾validate - validate the project is correct and all necessary information is available
◾compile - compile the source code of the project
◾test - test the compiled source code using a suitable unit testing framework. These tests should not require the code be packaged or deployed
◾package - take the compiled code and package it in its distributable format, such as a JAR.
◾integration-test - process and deploy the package if necessary into an environment where integration tests can be run
◾verify - run any checks to verify the package is valid and meets quality criteria
◾install - install the package into the local repository, for use as a dependency in other projects locally
◾deploy - done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects.
So to go through the above phases, we just have to call one command:
mvn <phase> { Ex: mvn install }
For the above command, starting from the first phase, all the phases are executed sequentially till the ‘install’ phase. mvn can either execute a goal or a phase (or even multiple goals or multiple phases) as follows:
mvn clean install plugin:goal
However, if you want to customize the prefix used to reference your plugin, you can specify the prefix directly through a configuration parameter on the maven-plugin-plugin in your plugin's POM.
A Build Phase is Made Up of Plugin Goals
Most of Maven's functionality is in plugins. A plugin provides a set of goals that can be executed using the following syntax:
mvn [plugin-name]:[goal-name]
For example, a Java project can be compiled with the compiler-plugin's compile-goal by running mvn compiler:compile.
Build lifecycle is a list of named phases that can be used to give order to goal execution.
Goals provided by plugins can be associated with different phases of the lifecycle. For example, by default, the goal compiler:compile is associated with the compile phase, while the goal surefire:test is associated with the test phase. Consider the following command:
mvn test
When the preceding command is executed, Maven runs all goals associated with each of the phases up to and including the test phase. In such a case, Maven runs the resources:resources goal associated with the process-resources phase, then compiler:compile, and so on until it finally runs the surefire:test goal.
However, even though a build phase is responsible for a specific step in the build lifecycle, the manner in which it carries out those responsibilities may vary. And this is done by declaring the plugin goals bound to those build phases.
A plugin goal represents a specific task (finer than a build phase) which contributes to the building and managing of a project. It may be bound to zero or more build phases. A goal not bound to any build phase could be executed outside of the build lifecycle by direct invocation. The order of execution depends on the order in which the goal(s) and the build phase(s) are invoked. For example, consider the command below. The clean and package arguments are build phases, while the dependency:copy-dependencies is a goal (of a plugin).
mvn clean dependency:copy-dependencies package
If this were to be executed, the clean phase will be executed first (meaning it will run all preceding phases of the clean lifecycle, plus the clean phase itself), and then the dependency:copy-dependencies goal, before finally executing the package phase (and all its preceding build phases of the default lifecycle).
Moreover, if a goal is bound to one or more build phases, that goal will be called in all those phases.
Furthermore, a build phase can also have zero or more goals bound to it. If a build phase has no goals bound to it, that build phase will not execute. But if it has one or more goals bound to it, it will execute all those goals.
Built-in Lifecycle Bindings
Some phases have goals bound to them by default. And for the default lifecycle, these bindings depend on the packaging value.
Maven Architecture:
Reference 1
Reference 2
Eclipse sample for Maven Lifecycle Mapping
The chosen answer is great, but still I would like to add something small to the topic. An illustration.
It clearly demonstrates how the different phases binded to different plugins and the goals that those plugins expose.
So, let's examine a case of running something like mvn compile:
It's a phase which execute the compiler plugin with
compile goal
Compiler plugin got different goals. For mvn compile it's mapped to a specific goal, the compile goal.
It's the same as running mvn compiler:compile
Therefore, phase is made up of plugin goals.
Link to the reference
The definitions are detailed at the Maven site's page Introduction to the Build Lifecycle, but I have tried to summarize:
Maven defines 4 items of a build process:
Lifecycle
Three built-in lifecycles (aka build lifecycles): default, clean, site. (Lifecycle Reference)
Phase
Each lifecycle is made up of phases, e.g. for the default lifecycle: compile, test, package, install, etc.
Plugin
An artifact that provides one or more goals.
Based on packaging type (jar, war, etc.) plugins' goals are bound to phases by default. (Built-in Lifecycle Bindings)
Goal
The task (action) that is executed. A plugin can have one or more goals.
One or more goals need to be specified when configuring a plugin in a POM. Additionally, in case a plugin does not have a default phase defined, the specified goal(s) can be bound to a phase.
Maven can be invoked with:
a phase (e.g clean, package)
<plugin-prefix>:<goal> (e.g. dependency:copy-dependencies)
<plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal> (e.g. org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile)
with one or more combinations of any or all, e.g.:
mvn clean dependency:copy-dependencies package
I believe a good answer is already provided, but I would like to add an easy-to-follow diagram of the different 3 life-cycles (build, clean, and site) and the phases in each.
The phases in bold - are the main phases commonly used.
Credit to Sandeep Jindal and Premraj. Their explanation help me to understand after confused about this for a while.
I created some full code examples & some simple explanations here https://www.surasint.com/maven-life-cycle-phase-and-goal-easy-explained/ . I think it may help others to understand.
In short from the link, You should not try to understand all three at once, first you should understand the relationship in these groups:
Life Cycle vs Phase
Plugin vs Goal
1. Life Cycle vs Phase
Life Cycle is a collection of phase in sequence see here Life Cycle References. When you call a phase, it will also call all phase before it.
For example, the clean life cycle has 3 phases (pre-clean, clean, post-clean).
mvn clean
It will call pre-clean and clean.
2. Plugin vs Goal
Goal is like an action in Plugin. So if plugin is a class, goal is a method.
you can call a goal like this:
mvn clean:clean
This means "call the clean goal, in the clean plugin" (Nothing relates to the clean phase here. Don't let the word"clean" confusing you, they are not the same!)
3. Now the relation between Phase & Goal:
Phase can (pre)links to Goal(s).For example, normally, the clean phase links to the clean goal. So, when you call this command:
mvn clean
It will call the pre-clean phase and the clean phase which links to the clean:clean goal.
It is almost the same as:
mvn pre-clean clean:clean
More detail and full examples are in https://www.surasint.com/maven-life-cycle-phase-and-goal-easy-explained/
There are following three built-in build lifecycles:
default
clean
site
Lifecycle default -> [validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy]
Lifecycle clean -> [pre-clean, clean, post-clean]
Lifecycle site -> [pre-site, site, post-site, site-deploy]
The flow is sequential, for example, for default lifecycle, it starts with validate, then initialize and so on...
You can check the lifecycle by enabling debug mode of mvn i.e., mvn -X <your_goal>
Maven working terminology having phases and goals.
Phase:Maven phase is a set of action which is associated with 2 or 3 goals
exmaple:- if you run mvn clean
this is the phase will execute the goal mvn clean:clean
Goal:Maven goal bounded with the phase
for reference
http://books.sonatype.com/mvnref-book/reference/lifecycle-sect-structure.html
In reference to Pace's answer,
If you specify a goal when you execute Maven then it will run that goal and only that goal. In other words, if you specify the jar:jar goal it will only run the jar:jar goal to package your code into a jar.
there is an exception to this statement. Maven Plugin API allows a goal to trigger execution of a lifecycle phase.
Consider the following project:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>simple-maven-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
</project>
When you execute the goal run defined in spring-boot-maven-plugin
mvn org.springframework.boot:spring-boot-maven-plugin:run
it prints
[INFO] ------------------< org.example:simple-maven-project >------------------
[INFO] Building simple-maven-project 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] >>> spring-boot-maven-plugin:3.0.0:run (default-cli) > test-compile # simple-maven-project >>>
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) # simple-maven-project ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory C:\Users\Bartosz\IdeaProjects\simple-maven-project\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) # simple-maven-project ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) # simple-maven-project ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory C:\Users\Bartosz\IdeaProjects\simple-maven-project\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) # simple-maven-project ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] <<< spring-boot-maven-plugin:3.0.0:run (default-cli) < test-compile # simple-maven-project <<<
[INFO]
[INFO]
[INFO] --- spring-boot-maven-plugin:3.0.0:run (default-cli) # simple-maven-project ---
[INFO] ------------------------------------------------------------------------
This is because the goal definition in spring-boot-maven-plugin-X.X.X.jar/META-INF/maven/plugin.xml contains <executePhase>test-compile</executePhase>, which executes test-compile and all the preceding phases.
<mojo>
<goal>run</goal>
(...)
<executePhase>test-compile</executePhase>
(...)
</mojo>
Moreover, because of the default bindings for the "jar" packaging, few other goals are executed. If the packaging is changed to "pom", the same command results with
[INFO] ------------------< org.example:simple-maven-project >------------------
[INFO] Building simple-maven-project 1.0-SNAPSHOT
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] >>> spring-boot-maven-plugin:3.0.0:run (default-cli) > test-compile # simple-maven-project >>>
[INFO]
[INFO] <<< spring-boot-maven-plugin:3.0.0:run (default-cli) < test-compile # simple-maven-project <<<
[INFO]
[INFO]
[INFO] --- spring-boot-maven-plugin:3.0.0:run (default-cli) # simple-maven-project ---
[INFO] ------------------------------------------------------------------------
because there are no default bindings for test-compile or any previous phase and this packaging type.
Related
A few basic questions on ci/cd pipelines.
When we build java code, do we create jar file before going for sonarqube analysis or does both happen simultaneously. My understanding is sonarqube analysis needs to be performed before maven build. Build should happen only if codequality crosses our quality checks.
Does sonar scanner and maven are used individually or sonar scanner is integrated with maven. I know both are possible but what is the best way that we need artifacts to be created only if code passes quality checks.
How does the sonarqube tell CI system (be it azuredevops or any other system) whether to go for next steps or break if the quality check is failed.
Usually you run your full build (which contains building the jar file or in general artifacts) and the sonar analysis will be done afterwards (unit tests coverage, static code analysis etc.) and no it is not done before it's done afterwards otherwise it would not be possible to integrate results like code coverage of the unit/integration test into the sonarqube analysis.
Technically the sonar scanner can be triggered via the Maven build (it is done via a maven plugin) and often called like this: mvn verify sonar:sonar(assumed that it is configured correctly).
SonarQube has a webhook which will be called/triggered if the quality is not as expected. Most of the time the CI/CD system have a stage which will shows the result of that and makes the final result of the build "red". Also many source code hosting solutions (GitHub, GitLab, Gitea or alike) having indicators which shows that (usually) within a pull request...
Update:
If you run sonar analysis on a project without compiling the code you will get this:
$ mvn clean sonar:sonar
[INFO] JavaClasspath initialization
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.952 s
[INFO] Finished at: 2022-12-04T21:41:34+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.sonarsource.scanner.maven:sonar-maven-plugin:3.9.1.2184:sonar (default-cli) on project kata-fraction:
Your project contains .java files, please provide compiled classes with sonar.java.binaries property, or exclude them from the analysis with sonar.exclusions property. -> [Help 1]
[ERROR]
I'm looking for a (supported) mvn based command, which will give me a list of all the GroupID:ArtifactID:Version (GAV) for all artifacts that running a mvn package command would produce.
For a single module Maven project, with no parent pom, this is trivial: you can look inside the pom.
For a single module Maven project, with a parent pom, you could use help:effective-pom and it will present a pom file with the <version> element present.
For a multi module Maven project (reactor), you could actually do the same (didn't think so, learned so just now by trying it out). This will allow parsing the file for (multiple) <project> elements.
Anything else to consider?
The overall goal of this, is to be able to feed a downstream Continuous Delivery (http://go.cd/) stage/step/job with information on what version of it's upstream dependencies should be used.
In general you can't produce a list before the build has run...The problem is that based on the pom model not all artifacts are described, cause some plugins can produce supplemental artifacts (maven-assembly-plugin, maven-shade-plugin, maven-jar-plugin via test-jar etc.)
What you can make is to get a list of produced artifacts after a build has run..(installed). The question of yours inspired me to implement an EventSpy which produces such list at the end of the build...which looks like this:
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.423 s
[INFO] Finished at: 2016-05-08T13:22:10+02:00
[INFO] Final Memory: 24M/310M
[INFO] ------------------------------------------------------------------------
[INFO] -- Maven Artifact Collector Summary --
[INFO] ------------------------------------------------------------------------
[INFO] test.maven.plugin.profiler:parse-pom:0.1.0-SNAPSHOT:jar
[INFO] test.maven.plugin.profiler:parse-pom:0.1.0-SNAPSHOT:pom
[INFO] test.maven.plugin.profiler:parse-pom:0.1.0-SNAPSHOT:jar:jar-with-dependencies
What i can do is to enhance that and write a file which contains the information (in more or less any format)...At the moment it's just a PoC...May be you can give some more information or create issues or PR's and request what might be needed...may be this is also interesting for others...
Furthermore your downstream part must have those artifacts within a repository cache available (either on a file system or via a repository manager or docker data container)...
I have a little bit of strange Problem with Jenkins, Maven and Tycho and it is hard to find out who is the culprit.
All SCM Triggered Builds fail but all manually triggered builds succeed.
Jenkins Version : Jenkins ver. 1.527
Maven Version : 3.05
I have a modularized tycho build:
<modules>
<module>../main.plugin.test</module>
<module>../main.plugin.internationalization.at</module>
<module>../crud.plugin</module>
<module>../rest.plugin</module>
<module>../main.plugin</module>
<module>../main.feature</module>
<module>../product</module>
<module>../target-definition</module>
<module>../rest.plugin.test</module>
</modules>
Jenkins is configured as a simple maven build with modules.
It just executes:
-X clean deploy
When an SCM-Build is triggered some modules are not build.
When I build it manually everything is fine:
This behaviour is consistent. I already tried
switching to a different Maven version (3.05 / 3.04)
deleting the whole workspace prior to building
clean checkout of all sources
running of -X deploy (without clean)
Any amount of manual invocations succeeds. And any amount of scm triggers fails.
Both Maven logs look exactly the same until (working):
[INFO] Reactor Build Order:
[INFO]
[INFO] client-master
[INFO] crud-plugin
[INFO] main-plugin
[INFO] ------------.main.plugin.test
[INFO] ------------.main.plugin.internationalization.at
[INFO] rest-plugin
[INFO] main-plugin
[INFO] ------------.product
[INFO] target-definition
[INFO] ------------.rest.plugin.test
and (failing):
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] main-plugin
[INFO] ------------.plugin.test
[INFO] ------------.main.plugin.internationalization.at
[INFO] rest-plugin
[INFO] main-plugin
[INFO] ------------.product
[INFO] ------------.rest.plugin.test
The final error message therefore is:
Caused by: java.lang.IllegalStateException: ------------..client:------------..crud.plugin:eclipse-plugin:1.0.0-SNAPSHOT does not provide an artifact with classifier 'null'
Customer specific module names are replaced with ------------. in this question.
I have heard repeatedly of vague problems with Tycho builds on Jenkins. The reason for these problems seems to be that some Jenkins plugin triggering these builds hooks into the Maven lifecycle and this somehow collides with what Tycho does in the Maven internals.
For the problem that you are describing, it seems that the Jenkins plugin that you are using is changing the module build order. This may be okay for a normal Maven build (where all dependencies are declared in the POMs), but may fail for a Maven/Tycho build, where dependencies are computed by Tycho during the build.
To avoid this problem, you should trigger the Maven build in a way that is closer to a normal command line build. I found that the Invoke top-level Maven targets build step from the Maven Integration plugin works without problems.
Forgive me. I'm a noob at Maven.
Here is my maven project directory:
project/
pom.xml
moduleA/
moduleB/
sub-moduleA/
sub-moduleB/
sub-moduleC/
moduleC/
Of course, within each module and sub-module, they have their own pom.xml. Also, in this example moduleB depends on moduleA and moduleA depends on moduleC. I know in maven there are multiple phases it goes through, but does it take each phase one at a time, or take each module one at a time. Right now, the only three phases I'm concerned with is compile, package, and install.
For example:
Does it do it in Order 1:
compile moduleC
compile moduleA
compile moduleB
package moduleC
package moduleA
package moduleB
install moduleC
install moduleA
install moduleB
Or does it do it in Order 2:
compile moduleC
package moduleC
install moduleC
compile moduleA
package moduleA
install moduleA
compile moduleB
package moduleB
install moduleB
Or does it do it in a totally different order, or am I just completely off in my understanding in maven?
I'm running Maven 2.2.1. Thanks!
Order 2 : The reactor detects all the projects, build a sorted list to build the projects in the right order (respecting dependencies), and then builds the projects, following this order.
If A depends on B, you cannot start to build A if B is not totally processed.
I don't mean to be snippy, but you should familiarize your self with the maven output. It really does tell you precisely what it's doing. It will tell you precisely the order in which it will build the modules, and then it will tell you precisely the phase / executions that are going on while it builds each.
For instance, here's a simplified built report. First, it tells you what project its building. Then, for each phase there's a report about which mojo execution is occuring. Note that the execution lines start and end with three --- ( this is maven 3; it's different in maven 2 ). And note that it tells you:
the name of the plugin, e.g. maven-clean-plugin
The version of the plugin
The name of the goal on the plugin that's being executed
The name of the execution, e.g. default-clean
Note, all of the executions that are the default binding for the lifecycle phases, i.e. the built in executions, have a name like default-clean where the phase is identified, as well as the fact that it's the default.
[INFO] ------------------------------------------------------------------------
[INFO] Building common-utilities 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.3:clean (default-clean) # common ---
SNIP
[INFO] --- maven-resources-plugin:2.5:resources (default-resources) # common ---
SNIP
[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) # common ---
SNIP
[INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) # common ---
First, I'd suggest to work with Maven 3 rather than 2, migration from the latter to the former is really simple (sometimes you can do it without changing anything) and you will notice a high improvement in performance.
Besides, regarding the build order, you should read a bit about the Maven Reactor, the system in charge of processing multi-module projects.
I have maven parent project with several child projects. On deploy I want to execute some complex scp tasks. When i run mvn deploy i have error:
[INFO] Reactor Summary:
[INFO]
[INFO] Child project1 ............................... FAILURE [0.331s]
[INFO] Child project 2 .............................. SKIPPED
[INFO] Child project 3 .............................. SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.5:deploy
(default-deploy) on project Parent: Deployment failed: repository element
was not specified in the POM inside distributionManagement element or in -DaltDeploymentRepository=id::layout::url parameter -> [Help 1]
I read the question Deployment issue with Maven Plugin it says that i need to define repository in settings.xml. But i don't have any repository, all I want to do on deploy phase is execute script that copy files on server and do other work. And I want to execute this script only in parent project and scip this phase in child.
I've not worked with maven very much, so maybe i'm just missing some maven concept.
If you don't have a repository (meaning: deployment/project repository, not local that you must have), then don't run mvn deploy, but rather mvn install. Maven Release Plugin (bound to the deploy phase by default) is for installing your artifacts in your project repository, labelling it in the source control repository, stuff like that. Which means: you have to define repositories and source control connection in your main POM, and perhaps credentials for your repository access in settings.xml.
If you want to skip certain projects (included as <modules>, right?), I think your best option is to use profiles with different <modules> sections inside for every profile.