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

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.

Related

How to fix not finding a plugin artifact?

I am getting this error: [ERROR] Plugin org.apache.maven.plugins:maven-surefire-plugin:2.12.4 or one of its dependencies could not be resolved: Could not find artifact org.apache.maven.plugins:maven-surefire-plugin:jar:2.12.4 in nexus-xyz-plugin
I tried to run maven with dependecy:tree, but I can't see surefire, and I dont know why it is looking for this specific version 2.12.4 which is not specified in my pom!
Even the surefire plugin is not defined in my pom, but I have the assembly plugin not sure if assembely is dependent on surefire
Note that I only get the error when running mvn package, however when running mvn compile the build succeeds
Version 2.12.4 of the maven-surefire-plugin is always added to the pom by maven version 3.x unless you depend on a specific other version.
Maven has a so called super pom that you get for free, but that doesn't list surefire: https://maven.apache.org/ref/3.8.5/maven-model-builder/super-pom.html
However it is added to the pom, i've checked this with maven 3.3.9. You can verify this by running mvn help:effective-pom.
Reference with the same problem: No surefire plugin in my pom - How does it show surefire output?
These plugin versions are part of the default bindings for lifecycle executions, in this case of the test phase. So these plugins are always included if not specified.
See for reference:
https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
https://maven.apache.org/ref/3.8.5/maven-core/default-bindings.html
Maven default life-cycle and plugins section
Normally this plugin should be available in maven central, check if you have a <pluginRepository> in your (effective) pom that references https://repo1.maven.org/maven2/
Some other things you can check:
Open the file .m2\repository\org\apache\maven\plugins\maven-surefire-plugin\2.12.4\maven-surefire-plugin-2.12.4.jar.lastUpdated and check the error message for each repository. Check why it can't reach maven central; is it missing from the list or giving an error? This might be a company firewall/policy issue perhaps? Or is it giving an error on HTTPS/TLS protocol level?
Check if you can add maven central to your repositories list if it's missing somehow (should be included by default). Check if it's HTTP or HTTPS, only secure is supported now.
Run your maven command with -X for debug mode to investigate further
An alternative is to add the latest version of surefire to your project that is available in your plugin-repository, and perhaps disable it if you're not executing unit tests.
See Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12:test (default-test) on project.

How to run just generate goal from swagger codegen maven plugin

I am using the swagger codegen maven plugin to generate a server stub from a swagger spec. If I run mvn compile then it generates properly and compiles the project. However, sometimes I want to run just the generate.
Specifically, I'd like to avoid both compiling the whole project and also running another plugin (checkstyles) which runs in the validate phase. Ideally, I'd like to generate the generated classes from the swagger spec and compile those classes but not the project as a whole.
The use case here is that while developing I may need to update the spec and re-generate at points when the project as a whole isn't valid (or won't be, with the new spec). I've read that you can use "prefix:goal". I've tried the following, but none work:
mvn swagger-codegen-maven-plugin:generate
mvn swagger-codegen:generate
mvn swagger:generate
mvn codegen:generate
It gives (e.g.)
No plugin found for prefix 'codegen' in the current project and in the
plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available
from the repositories
I also read that you could use "groupid:artificatid:version_goal" so I tried:
mvn io.swagger:swagger-codegen-maven-plugin:2.4.0-SNAPSHOT:generate
This seems to get further but gives an error
Failed to execute goal
io.swagger:swagger-codegen-maven-plugin:2.4.0-SNAPSHOT:generate
(default-cli) on project com.carus.api.base: The parameters
'inputSpec', 'language' for goal
io.swagger:swagger-codegen-maven-plugin:2.4.0-SNAPSHOT:generate are
missing or invalid
My pom structure is slightly complex. There are several APIs. Each is in some ways their own project. They have a common parent pom with the execution goal in, and the project pom only sets certain variables. The variable used as inputSpec is defined in the project pom, but the one for language in the base pom. (The .base project mentioned here is actually where the base pom is, and is an abstract package (<packaging>pom</packaging>). If I specify a specific project I get the same error but referring to that project.
Questions:
Can I even achieve what I want (generate code from the spec and
compile just that code but not the whole project) with a goal?
How to find out what "prefix" to use for the "prefix:goal" syntax?
The closest I have come is run mvn generate-sources -Dcheckstyle.skip=true. This generates but I don't think it compiles the generated classes. So I then have to clean the project in Eclipse to trigger it to recompile.
How to find out what "prefix" to use for the "prefix:goal" syntax?
The prefix for the plugin should be in this file: "swagger-maven-plugin-2.3.1.jar/META-INF/maven/com.github.kongchen/swagger-maven-plugin/plugin-help.xml".
<plugin>
<name>Swagger Maven Plugin</name>
...
<goalPrefix>swagger</goalPrefix>
...

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

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

How to add files to a maven project executing generate goal (mvn archetype:generate)?

I'm building a maven archetype project. As parameter (serviceDescriptor), I'm passing path to an xml file. When the generate goal is successfully executed, I would like to have the serviceDescriptor file in src/main/resources. Based on maven archetype documentation, it seems that is not possible but, there should be a way to do it.
I have spent couple of days on this and I think that I have found a reasonable solution.
As I mention in the question, I'm passing the file path as required property to the archetype:generate.
I had to implement a simple plug-in that is executed after archetype generate is finishing. This plug-in is coping the file into src/main/resources, read some data from the file and update the pom.xml setting some properties. In order to be able to modify the pom.xml file I'm using maven-model-2.0 archetype as dependency in maven plug-in. It offers Maven MvenXpp3Reader and MavenXpp3Writer classes that allows to safe modify pom.xml.
In order to tell to archetype project to execute plug-in at the end of generate phase of archetype:
mvn archetype:generate -goals=plugin_groupId:plugin_artifactId:goal
The downside is that the plug-in should be available in a accessible repository or local repo.

Resources