What is a prefix and why do we need it?
You have just encountered Maven Plugin Resolution Prefix . This is a function that allows the user to call the targets of a specific Maven plugin using its prefix. When you invoke the target directly on the command line, you can use the fully functional form:
mvn my.plugin.groupId:foo-maven-plugin:1.0.0:bar
This will call the bar target of the Foo Maven plugin with the coordinates my.plugin.groupId:foo-maven-plugin:1.0.0 (in the form of groupId:artifactId:version ). It works well, but it is a bit detailed. It would be nice to resort to this goal in a simpler way without specifying all of these coordinates. Maven makes this possible by assigning prefixes to plugins, so you can refer to this prefix instead of integer coordinates:
mvn foo:bar ^^^ ^^^ | | prefix | | goal
How is this prefix defined?
You can define a prefix for each Maven plugin. This corresponds to the simple name used to identify it:
Traditional artifact identifier formats for use are:
maven-${prefix}-plugin - for official plugins supported by the Apache Maven team itself (you should not use this naming pattern for your plugin, see this note for more information).${prefix}-maven-plugin - for plugins from other sources
If your artifactId plugin matches this pattern, Maven automatically matches your plugin with the correct prefix in the metadata stored in your plugin groupId path in the repository.
In other words, if your plugin artifact identifier is named foo-maven-plugin , Maven will automatically assign it the prefix foo . If you do not want this destination by default, you can configure your own using maven-plugin-plugin and its goalPrefix .
How are Maven map prefixes for plugins?
In a team
mvn foo:bar
Maven should have a way to conclude that foo actually means my.plugin.groupId:foo-maven-plugin . In the settings.xml file you can add groups of plugins in the form:
<pluginGroups> <pluginGroup>org.mortbay.jetty</pluginGroup> </pluginGroups>
What this means, says Maven, which group identifier should he consider when you use the prefix in the command. By default and in addition to the groups specified in the settings, Maven also searches for group identifiers org.apache.maven.plugins and org.codehaus.mojo . It performs a default search after the ones you configured in the settings. Therefore, with the above configuration and the mvn foo:bar command, Maven will look for the plugin with the foo prefix inside the id group org.mortbay.jetty , org.apache.maven.plugins and org.codehaus.mojo .
The second step is how this search is actually performed. Maven will download metadata files (or view them in your local repository, if they are already loaded), called maven-metadata.xml , from each remote repository in these group identifiers. If we take an example where the only remote repository we have is Maven Central, Maven will first download http://repo1.maven.org/maven2/org/mortbay/jetty/maven-metadata.xml and look inside this file if we have something that displays foo . Notice how the group identifier was converted to a directory structure in the remote repository. The structure of this metadata file is:
<metadata> <plugins> <plugin> <name>Some Awesome Maven Plugin</name> <prefix>somePrefix</prefix> <artifactId>some-maven-plugin</artifactId> </plugin> </plugins> </metadata>
If none of the <plugin> sections contains a <prefix> that matches the one we specified ( foo ), Maven will continue the next group identifier by clicking <code> http://repo1.maven.org/maven2/org/codehaus/mojo /maven-metadata.xmlcode> . Again, if none are found, Maven will finally hit http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-metadata.xml (note the Downloading: logs in mvn jetty:run , just getting these last two files). If none of them are found, Maven can do nothing else for you, and this will be an error:
[ERROR] The plugin was not found for the prefix 'foo' in the current project and in the plugin groups [org.mortbay.jetty, org.apache.maven.plugins, org.codehaus.mojo] accessible from the repositories [local (... / . m2 / repository), central ( http://repo.maven.apache.org/maven2)] → [Help 1]
This is the mistake you have here. However, if one match was made during this search, then Maven can use <artifactId> to use.
Now this means that it has a group identifier and an artifact identifier. The final piece of the puzzle is the version
Which version will be used?
Maven will use the latest available if it is not explicitly configured in the POM (see the next section). All possible versions are extracted by extracting another metadata file, which is still called maven-metadata.xml , but this time it lives with the artifact identifier folder in the repository (unlike above, where it was next to the group identifier). Taking the Maven Clean plugin example (the group ID and artifact ID will be found with the above mechanism and the mvn clean:clean command), maven-metadata.xml looks like this:
<metadata> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-clean-plugin</artifactId> <versioning> <latest>3.0.0</latest> <release>3.0.0</release> <versions> <version>2.0-beta-1</version> <version>2.0-rc1</version> <version>2.0</version> <version>2.1</version> <version>3.0.0</version> </versions> <lastUpdated>20151022205339</lastUpdated> </versioning> </metadata>
Maven will select the version of <release> as the version, which is the latest version of the plugin version. If this tag is not present, it will select <latest> , which are the latest version of the plugin, release, or snapshot. It may happen that there are no both tags, in which case Maven will choose the first version or the first snapshot due to the lack of release , a list of <version> elements.
If this still fails, Maven can do nothing else for you, the version cannot be displayed, and these are errors. However, this is unlikely to happen. Now we have collected the group identifier, artifact identifier and version; to finally call the bar target of our plugin.
What is the problem with my configuration?
As mentioned above, Maven looks at certain predefined group identifiers within active remote repositories to look for matches with a given prefix. Using command
mvn findbugs:findbugs
Maven starts a search with the findbugs prefix. Since our configuration does not have a <pluginGroup> in our settings, Maven looks at the group identifier org.codehaus.mojo and org.apache.maven.plugins to match the prefix.
And he finds one: Findbugs Maven Plugin is published under the group ID org.codehaus.mojo ; indeed, you can find in maven-metadata.xml :
<plugin> <name>FindBugs Maven Plugin</name> <prefix>findbugs</prefix> <artifactId>findbugs-maven-plugin</artifactId> </plugin>
And you can also find the version that will be used by looking at the maven-metadata.xml file in findbugs-maven-plugin just displayed (3.0.4 at the time of this writing and note how it exactly matches the version in mvn findbugs:findbugs your question). So the permission succeeded, and then Maven can continue to refer to findbugs target of this plugin.
The second example is the command
mvn jetty:run
As before, the same resolution steps occur, but in this case you will find that the <jetty> prefix is not displayed in any of the maven-metadata.xml for the id group org.codehaus.mojo and org.apache.maven.plugins , Thus, the permission fails, and Maven returns the error that you have.
But we saw how to make it work! We can add <pluginGroup> inside our settings so that this group identifier can also be searched at the time of resolution. Jetty Maven Plugin is published under the id group org.eclipse.jetty , and if we look at the corresponding maven-metadata.xml in Maven Central , you will see that there is <prefix>jetty</prefix> . So the fix is simple: just define this new group id to search inside the settings:
<pluginGroups> <pluginGroup>org.eclipse.jetty</pluginGroup> </pluginGroups>
Now, Maven will also consider this group identifier and successfully combine the jetty prefix with org.eclipse.jetty:jetty-maven-plugin .
How can I use a specific version? Or I do not want to change my settings!
Of course, all this permission can be tracked if you clearly define the plugin in your POM, and this is another solution that you found:
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.2.11.v20150529</version> </plugin>
and use
mvn jetty:run
If you configure the plugin directly in the POM, prefix resolution still occurs, but it is slightly masked: Maven will download the plugin from the configured remote repositories and will download and install all metadata files along this path, including maven-metadata.xml containing the jetty prefix jetty . Since it automatically loads it, a search is always performed.
Note also that since the plugin was defined in POM, you do not need <pluginGroup> in the settings: the group ID was recorded in POM. In addition, it ensures that version 9.2.11.v20150529 is used, not the latest.