Maven plugins binding when no execution details is specified in POM - maven

When no execution details is specified for a plugin in the POM file, then is there a default phase of the maven lifecycle to which the plugin is bind to?
I assume the plugin could only be called explicitly via the command line in this scenario.

The execution of plugins depends on the phase (life cycle) you're calling and the artifact type you're producing e.g. when your project produces a pom (<packaging>pom</packaging>) instead of a jar (jar or no <packaging> element specified), the compile plugin is not called at all.
For a list of executed goals (plugins) see
the complete Maven reference.
If you want to check what plugins are configured for your project, check the effective pom which can be created by calling
mvn help:effective-pom
The effective pom is a merge of the super pom and your project's pom.
see this tutorial for an example of an effective pom

There are different things. First the life cycle which defines executions of particular plugins.
Apart from that a plugin can define a default life cycle phase where it will be executed which is defined by the plugin author.
For example the xml-maven-plugin binds to the generate-resources phase. Excerpt from the docs:
Requires a Maven project to be executed.
Binds by default to the lifecycle phase: generate-resources.
Here the plugin binds by default to the generate-resources life cycle phase. Or you can look at the maven-ear-plugin and many other plugins.
Of course you can call a plugin via command line if the appropriate plugin supports that. Otherwise you can bind the plugin via execution block to a particular life cycle phase.

Related

Maven: How is a phase mapped to a lifecycle

i'm wondering about how Maven maps a phase to a lifecycle.
For example when running
mvn clean
then Maven executes the phases "pre-clean" and "clean" of the "clean" lifecycle.
But how does Maven determine that the phase "clean" (as provided as command line argument) belongs to the "clean" lifecycle? There could be another lifecycle that also has a "clean" phase.
It may be a rule that all phases over all lifecycles must have a unique name. But i don't know.
In Maven there existing only the following three life cycles
clean
default
site
The details are defined in the lifecycle binding of Maven core https://maven.apache.org/ref/3.8.1/maven-core/lifecycles.html
The existing and defined life cycles are defined in the following file:
META-INF/plexus/components.xml

Phase name collisions in custom lifecycles in Maven?

AFAIK, you can create a custom build lifecycle in maven.
Also, AFAIK, you cannot tell maven to execute a lifecycle. You can either:
Tell maven to execute a phase: In this case, maven finds in which lifecycle this phase is, and then executes all phases in that lifecycle, up to the phase specified.
Tell maven to execute a goal, by specifying it as mvn plugin_name:goal_name
So, assume that I have created a custom lifecycle. And assume that this custom lifecycle has a phase named install.
When I write mvn install, will maven execute the default lifecycle (which has a phase named install) or my custom lifecycle (which also has a phase named install)?
How will maven determine which lifecycle to follow?
This is not supported (yet), though recently Stephen started a thread about it: http://maven.markmail.org/thread/z57dzgunecgfcrf7

How do I set up a TeamCity build job to execute a maven job with no pom

We have an in-house developed MOJO that generates content and doesn't require you to have an existing project or POM. Think of the maven archetype plugin, where you can just run mvn [mojo]:[goal] and have maven just execute that goal without a POM.
This MOJO connects to a specific database instance in a specific environment, and generates some metadata for the contents of the database, so our testers can inspect the metadata and locate production-like data that has certain attributes they need for a given test.
When you execute the metadata mojo, maven resolves the MOJO from the available repo's (in our case an Artifactory repo), and it then does its work and returns. It does not create any artifacts or other outputs.
We use TeamCity as our CI server, but it also has metadata generation jobs so with one click a dev can kick of a metadata generation job against a specific database.
The problem with this is the Maven runner in TeamCity requires a POM. If TC hasn't already checked out a project from a VCS, or the project it's checked out doesn't have a POM, the maven runner won't do anything. In this case, there is nothing to check out (the MOJO is resolved from Artifactory) so there is no POM.
I can set up the TC job to use the Command Line runner and have it execute, say, mvn com.example:metadata-generate -DenvironmentName=UAT1, but then it's impossible to specify the maven settings file that maven should use.
So my question is, how do I do this? Is it possible to have the maven runner execute an arbitrary maven command without needing a POM? Alternatively, using the Command line runner, is it possible to have a TC job copy a specific maven settings file to the build agent so it can be referenced in the maven command as mvn com.example:metadata-generate -DenvironmentName=UAT1 -s {path-to-settings-file}?
So its turns out that TC handles pom-less maven builds just fine. My problem was that the MOJO was not declared to not require a project.
Comparing my MOJO with the MavenArchetypePlugin source, I needed to declare my MOJO with the class level javadoc tag #requiresProject false.
Once I had that in place, TC ran my pom-less job perfectly well. All I had to do was clear the Path to POM file: field in the TC build configuration and leave it blank.
You can customize the name of the pom file that you use as an argument into the maven build-step in the teamcity and use this as the second "build step".Lets call the parameter as pom.file.name
In the first step , resolve all the in-house dependencies that you have and set the name of the pom file you want to execute into the variable pom.file.name
If you want to know more about how to change tha value of a variable in teamcity, you can read about it here

What is the purpose of the # symbol in <groupId>#project.groupId#</groupId>?

I'm trying to run 'mvn clean install' in a sub-module of a multi-module project. The project is Jacoco but I assume it's more an issue of me not understanding how Maven is being used here than an issue with Jacoco itself.
https://github.com/jacoco/jacoco/blob/master/jacoco-maven-plugin.test/it/it-site/pom.xml
I get the following error:
[ERROR] Plugin #project.groupId#:jacoco-maven-plugin:#project.version#
or one of its dependencies could not be resolved: Failed to read
artifact descriptor for
#project.groupId#:jacoco-maven-plugin:jar:#project.version#
I see the following in the pom:
<groupId>#project.groupId#</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
I'm not familiar with using the # symbol in #project.groupId# although i assume it is somehow supposed to get substituted at runtime.
I can run Maven from the top level pom and I even see [INFO] Building: it-site/pom.xml in the log but a target directory is not created there.
A nudge in the right direction would be appreciated.
This probably has something to do with the pom file here: https://github.com/jacoco/jacoco/blob/master/jacoco-maven-plugin.test/pom.xml
It is using a plugin called the maven invoker.
The Invoker Plugin is used to run a set of Maven projects. The plugin can determine whether each project execution is successful, and optionally can verify the output generated from a given project execution.
And if you read about filtering files with this plugin, it mentions:
POM files selected by the include/exclude patterns. The tokens to be filtered must be enclosed in #...# to avoid interferences with Maven's normal POM interpolation, i.e. use #project.version# instead of ${project.version}.
Regarding why the Invoker Plugin and filtering is being used here...
The Spring Boot documentation provides some relevant background on why that is. Although the docs are for Spring Boot, i think it applies to testing all plugins (which Jacoco is).
Multi-module Maven builds cannot directly include maven plugins that
are part of the reactor unless they have previously been built. ...
The standard build works around this restriction by launching the
samples via the maven-invoker-plugin so that they are not part of the
reactor.
The sample application are used as integration tests during the build
(when you mvn install). Due to the fact that they make use of the
spring-boot-maven-plugin they cannot be called directly, and so
instead are launched via the maven-invoker-plugin.

How to get all Maven plugins & their versions for a specific phase?

Do you know of a way to list all Maven plugins (with their versions) that are going to be executed for a particular phase? This should include all plugins set in all parents of the current project.
One method would be to run:
mvn help:effective-pom
That will show you the projects POM after interpolation and inheritance have been applied. It should be fairly easy to look in the build configuration and determine the configured plugins for a phase from there.
http://maven.apache.org/plugins/maven-help-plugin/effective-pom-mojo.html

Resources