What does maven do with a bogus packaging type? - maven

I'm working my way through learning a somewhat complicated maven build. I've found a module that is using a bogus packaging type, "custom-war" to be specific. If I execute:
mvn -e -X clean install
maven complains thus:
[DEBUG] Error looking up lifecycle mapping to retrieve optional mojos. Lifecycle
ID: clean. Error: Component descriptor cannot be found in the component repository:
org.apache.maven.lifecycle.mapping.LifecycleMappingcustom-war.
However, it appears to go ahead and execute clean:clean, so it must have made some decisions on which goals to map to the lifecycle phases. Can anyone provide some insight into the decision making of maven in the face of a bogus packaging type?
I think I should add that this custom module appears to be "defining it's own default lifecycle bindings"; I've found a component.xml file that defines goal bindings for phases of the default lifecycle. In the light of this, the error appears to be complaining that there are no bindings declared for clean, but the format of the component.xml doesn't appear to support that.

The clean phase runs through to completion because the goals that are bound to this phase are independent of the packaging.
What should be done in response to the command mvn install on the other hand is predicated on the packaging. Maven encountered an unknown packaging of "custom-war" and so it threw its hands up.
See correlation of phases to packaging at Maven.

Related

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.

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

Maven plugins binding when no execution details is specified in POM

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.

How to debug loading of wrong Maven plugin

In build section of my effective pom there is a Maven plugin that I don't want to use (it was used before, but now I want to remove it).
I removed this plugin from every parent of my project, but is is still applied.
How do I find out where this plugin declaration come from?
UPDATE:
It turns out this plugin was an implicit dependency of another one. It was not declared as such, but referenced from plugin's components.XML leading to runtime dependency injection. The problem was found by pure luck. I think the question is still relevant - it should be possible to find implicit plugin dependencies without wasting a day or two.
Have you run
mvn install
on the parent pom when you deleted the plugin from there?
When you run mvn from submodule it actually looks into your local repository for parent/siblings modules (jars, poms), not to filesystem (compared to maven using the result of the build when you run whole parent project build with submodules).
If it doesn't help, have a look if it's not coming from super pom. You can see super pom on maven website:
http://maven.apache.org/ref/3.0.5/maven-model-builder/super-pom.html

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.

Resources