Как создать плагин Maven
1. Введение
Maven предлагает большое количество плагинов, которые помогут нам в сборке нашего проекта. Однако мы можем найти случаи, когда этих плагинов недостаточно, и мы должны разработать свои собственные.
К счастью, Maven предоставляет несколько полезных инструментов, которые помогут нам в этом процессе.
В этом уроке мы будем довольно практичными и покажем пошагово, как создать плагин Maven с нуля.
Мы также покажем, как использовать его в наших проектах и как создавать для него документацию.
2. Создание плагина
В ходе этого руководства мы разработаем плагин counter-maven-plugin, который будет подсчитывать количество зависимостей, содержащихся в проекте. Очень важно соблюдать соглашение об именах плагинов, которое Maven рекомендует при выборе имени для нашего плагина.
В этом случае мы создали проект вручную, но мы также можем сделать это с помощью maven-archetype-mojo :
При этом мы должны обновить версии зависимостей по умолчанию, чтобы использовать самые последние.
3. Создание Mojo
Наш моджо будет отвечать за подсчет количества зависимостей проекта.
3.1. Добавление зависимостей
Перед созданием mojo нам нужно добавить некоторые зависимости в наш pom.xml :
3.2. Создание класса Mojo
Теперь мы готовы создать наш моджо!
Чтобы получить доступ к информации о проекте, мы должны добавить MavenProject в качестве параметра:
Этот объект будет внедрен Maven при создании контекста.
На этом этапе мы можем реализовать метод execute и подсчитать количество зависимостей проекта:
Метод getLog () обеспечивает доступ к журналу Maven. AbstractMojo уже обрабатывает свой жизненный цикл.
3.3. Добавление параметров
The parameter we’ve added before is read-only and can’t be configured by the user. Also, it’s injected by Maven so we could say it’s kind of special.
In this section, we’re going to add a parameter where users can specify the scope of the dependencies that we want to count.
Hence, let’s create a scope parameter in our mojo:
We’ve only set the property attribute. It allows us to set this property via the command line or a pom property. For the rest of the attributes, we’re fine with the default values.
Now we’ll modify our execute method to use this parameter and filter the dependencies when counting:
More advanced types of parameters are explained in the official documentation.
4. Testing the Plugin
We’re done with the development of the plugin. Let’s test it to see if it works!
First of all, we have to install the plugin in our local repository:
In the next sections, we’ll first see how to run our plugin from the command line. Then, we’ll also cover how to use it in a Maven project.
4.1. Executing Our Plugin
We can run the goal of a plugin in the command line by specifying its fully qualified name:
In our case, it looks like this:
However, if we’ve followed the plugin naming convention that we mentioned at the beginning of this tutorial, Maven will resolve the prefix of our plugin and we can shorten the command:
Notice that this command is using the latest version of the plugin. Also, keep in mind that we have to add our groupId to the pluginGroups of our settings.xml so Maven also searches in this group:
If we check the output of the command, we can see that the plugin counted the number of dependencies in the pom.xml of our plugin:
We can also set the scope parameter via command line properties:
Notice that the scope name is the one that we defined in the property attribute of our parameter in the mojo.
4.2. Using Our Plugin in a Project
Let’s test now our plugin by using it in a project!
We’re going to create a very simple Maven project with some dependencies that our plugin will count:
The last thing is to add our plugin to the build. We have to explicitly set that we want to run the dependency-counter goal:
Notice that we’ve specified the scope parameter in the configuration node. Also, we haven’t specified any phase because our mojo is attached to the compile phase by default.
Now, we just need to run the compile phase to execute our plugin:
And our plugin will print the number of test dependencies:
In this tutorial, we’re not covering how to write unit or integration tests for our plugin but Maven provides some mechanisms to do it.
5. Adding Documentation
When we create a Maven plugin, it’s important to generate documentation to make it easy for other people to use it.
We’ll briefly cover how to generate this documentation with maven-plugin-plugin.
maven-plugin-plugin is already included in the project, but we’re gonna update it to use the latest version.
Also, we’ll do the same for maven-site-plugin:
Then, we have to make sure that we’ve added javadoc to our Mojo and also add some metadata in the pom.xml of the plugin:
After that, we need to add a reporting section in our pom.xml:
Finally, we’ll generate the documentation with the maven site command:
Inside the target folder, we can find a site directory with all the HTML files generated. The plugin-info.html is the one containing the plugin documentation:
More options to add to our documentation can be found on the Maven plugin documentation guide.
6. Conclusion
In this tutorial, we’ve shown how to create a Maven plugin. We first implemented a simple plugin, which helped us see a typical Maven plugin project structure. Then, we covered some of the tools that Maven provides to help us develop plugins.
We’ve kept it simple to make things clearer, but at the same time, we’ve provided some useful links with the necessary information on how to create a more powerful plugin.
Как всегда, полный исходный код примеров доступен на GitHub.
Как написать maven плагин
This guide is intended to assist users in developing Java plugins for Maven.
Important Notice: Plugin Naming Convention and Apache Maven Trademark
Your First Plugin
In this section we will build a simple plugin with one goal which takes no parameters and simply displays a message on the screen when run. Along the way, we will cover the basics of setting up a project to create a plugin, the minimal contents of a Java mojo which will define goal code, and a couple ways to execute the mojo.
Your First Mojo
At its simplest, a Java mojo consists simply of a single class representing one plugin’s goal. There is no requirement for multiple classes like EJBs, although a plugin which contains a number of similar mojos is likely to use an abstract superclass for the mojos to consolidate code common to all mojos.
When processing the source tree to find mojos, plugin-tools looks for classes with either @Mojo Java 5 annotation or » goal » javadoc annotation. Any class with this annotation are included in the plugin configuration file.
A Simple Mojo
Listed below is a simple mojo class which has no parameters. This is about as simple as a mojo can be. After the listing is a description of the various parts of the source.
All Mojo annotations are described by the Mojo API Specification.
Project Definition
Once the mojos have been written for the plugin, it is time to build the plugin. To do this properly, the project’s descriptor needs to have a number of settings set properly:
groupId | This is the group ID for the plugin, and should match the common prefix to the packages used by the mojos |
artifactId | This is the name of the plugin |
version | This is the version of the plugin |
packaging | This should be set to » maven-plugin « |
dependencies | A dependency must be declared to the Maven Plugin Tools API to resolve » AbstractMojo » and related classes |
Listed below is an illustration of the sample mojo project’s pom with the parameters set as described in the above table:
Building a Plugin
There are few plugins goals bound to the standard build lifecycle defined with the maven-plugin packaging:
compile | Compiles the Java code for the plugin |
process-classes | Extracts data to build the plugin descriptor |
test | Runs the plugin’s unit tests |
package | Builds the plugin jar |
install | Installs the plugin jar in the local repository |
deploy | Deploys the plugin jar to the remote repository |
Executing Your First Mojo
The most direct means of executing your new plugin is to specify the plugin goal directly on the command line. To do this, you need to configure the hello-maven-plugin plugin in you project:
And, you need to specify a fully-qualified goal in the form of:
For example, to run the simple mojo in the sample plugin, you would enter » mvn sample.plugin:hello-maven-plugin:1.0-SNAPSHOT:sayhi » on the command line.
Tips: version is not required to run a standalone goal.
Shortening the Command Line
There are several ways to reduce the amount of required typing:
At this point, you can run the mojo with » mvn hello:sayhi «.
Attaching the Mojo to the Build Lifecycle
You can also configure your plugin to attach specific goals to a particular phase of the build lifecycle. Here is an example:
This causes the simple mojo to be executed whenever Java code is compiled. For more information on binding a mojo to phases in the lifecycle, please refer to the Build Lifecycle document.
Mojo archetype
To create a new plugin project, you could using the Mojo archetype with the following command line:
Parameters
It is unlikely that a mojo will be very useful without parameters. Parameters provide a few very important functions:
Defining Parameters Within a Mojo
Defining a parameter is as simple as creating an instance variable in the mojo and adding the proper annotations. Listed below is an example of a parameter for the simple mojo:
Configuring Parameters in a Project
Configuring the parameter values for a plugin is done in a Maven project within the pom.xml file as part of defining the plugin in the project. An example of configuring a plugin:
In the configuration section, the element name (» greeting «) is the parameter name and the contents of the element (» Welcome «) is the value to be assigned to the parameter.
Note: More details can be found in the Guide to Configuring Plugins.
Parameter Types With One Value
Listed below are the various types of simple variables which can be used as parameters in your mojos, along with any rules on how the values in the POM are interpreted.
Boolean
Integer Numbers
Floating-Point Numbers
Dates
Files and Directories
Plain Text
Enums
Enumeration type parameters can also be used. First you need to define your enumeration type and afterwards you can use the enumeration type in the parameter definition:
So lets have a look like you can use such enumeration in your pom configuration:
You can also use elements from the enumeration type as defaultValues like the following:
Parameter Types With Multiple Values
Listed below are the various types of composite objects which can be used as parameters in your mojos, along with any rules on how the values in the POM are interpreted. In general, the class of the object created to hold the parameter value (as well as the class for each element within the parameter value) is determined as follows (the first step which yields a valid class is used):
Once the type for the element is defined, the text in the XML file is converted to the appropriate type of object
Arrays
Array type parameters are configured by specifying the parameter multiple times. Example:
Collections
For details on the mapping of the individual collection elements, see Mapping Lists.
Properties
in the parameter configuration. Example:
Other Object Classes
Please see Mapping Complex Objects for details on the strategy used to configure those kind of parameters.
Using Setters
You are not restricted to using private field mapping which is good if you are trying to make you Mojos resuable outside the context of Maven. Using the example above we could name our private fields using the underscore convention and provide setters that the configuration mapping mechanism can use. So our Mojo would look like the following:
Note the specification of the property name for each parameter which tells Maven what setter and getter to use when the field’s name does not match the intended name of the parameter in the plugin configuration.
Как написать maven плагин
This guide is intended to assist users in developing Java plugins for Maven.
Important Notice: Plugin Naming Convention and Apache Maven Trademark
Your First Plugin
In this section we will build a simple plugin with one goal which takes no parameters and simply displays a message on the screen when run. Along the way, we will cover the basics of setting up a project to create a plugin, the minimal contents of a Java mojo which will define goal code, and a couple ways to execute the mojo.
Your First Mojo
At its simplest, a Java mojo consists simply of a single class representing one plugin’s goal. There is no requirement for multiple classes like EJBs, although a plugin which contains a number of similar mojos is likely to use an abstract superclass for the mojos to consolidate code common to all mojos.
When processing the source tree to find mojos, plugin-tools looks for classes with either @Mojo Java 5 annotation or » goal » javadoc annotation. Any class with this annotation are included in the plugin configuration file.
A Simple Mojo
Listed below is a simple mojo class which has no parameters. This is about as simple as a mojo can be. After the listing is a description of the various parts of the source.
All Mojo annotations are described by the Mojo API Specification.
Project Definition
Once the mojos have been written for the plugin, it is time to build the plugin. To do this properly, the project’s descriptor needs to have a number of settings set properly:
groupId | This is the group ID for the plugin, and should match the common prefix to the packages used by the mojos |
artifactId | This is the name of the plugin |
version | This is the version of the plugin |
packaging | This should be set to » maven-plugin « |
dependencies | A dependency must be declared to the Maven Plugin Tools API to resolve » AbstractMojo » and related classes |
Listed below is an illustration of the sample mojo project’s pom with the parameters set as described in the above table:
Building a Plugin
There are few plugins goals bound to the standard build lifecycle defined with the maven-plugin packaging:
compile | Compiles the Java code for the plugin |
process-classes | Extracts data to build the plugin descriptor |
test | Runs the plugin’s unit tests |
package | Builds the plugin jar |
install | Installs the plugin jar in the local repository |
deploy | Deploys the plugin jar to the remote repository |
Executing Your First Mojo
The most direct means of executing your new plugin is to specify the plugin goal directly on the command line. To do this, you need to configure the hello-maven-plugin plugin in you project:
And, you need to specify a fully-qualified goal in the form of:
For example, to run the simple mojo in the sample plugin, you would enter » mvn sample.plugin:hello-maven-plugin:1.0-SNAPSHOT:sayhi » on the command line.
Tips: version is not required to run a standalone goal.
Shortening the Command Line
There are several ways to reduce the amount of required typing:
At this point, you can run the mojo with » mvn hello:sayhi «.
Attaching the Mojo to the Build Lifecycle
You can also configure your plugin to attach specific goals to a particular phase of the build lifecycle. Here is an example:
This causes the simple mojo to be executed whenever Java code is compiled. For more information on binding a mojo to phases in the lifecycle, please refer to the Build Lifecycle document.
Mojo archetype
To create a new plugin project, you could using the Mojo archetype with the following command line:
Parameters
It is unlikely that a mojo will be very useful without parameters. Parameters provide a few very important functions:
Defining Parameters Within a Mojo
Defining a parameter is as simple as creating an instance variable in the mojo and adding the proper annotations. Listed below is an example of a parameter for the simple mojo:
Configuring Parameters in a Project
Configuring the parameter values for a plugin is done in a Maven project within the pom.xml file as part of defining the plugin in the project. An example of configuring a plugin:
In the configuration section, the element name (» greeting «) is the parameter name and the contents of the element (» Welcome «) is the value to be assigned to the parameter.
Note: More details can be found in the Guide to Configuring Plugins.
Parameter Types With One Value
Listed below are the various types of simple variables which can be used as parameters in your mojos, along with any rules on how the values in the POM are interpreted.
Boolean
Integer Numbers
Floating-Point Numbers
Dates
Files and Directories
Plain Text
Enums
Enumeration type parameters can also be used. First you need to define your enumeration type and afterwards you can use the enumeration type in the parameter definition:
So lets have a look like you can use such enumeration in your pom configuration:
You can also use elements from the enumeration type as defaultValues like the following:
Parameter Types With Multiple Values
Listed below are the various types of composite objects which can be used as parameters in your mojos, along with any rules on how the values in the POM are interpreted. In general, the class of the object created to hold the parameter value (as well as the class for each element within the parameter value) is determined as follows (the first step which yields a valid class is used):
Once the type for the element is defined, the text in the XML file is converted to the appropriate type of object
Arrays
Array type parameters are configured by specifying the parameter multiple times. Example:
Collections
For details on the mapping of the individual collection elements, see Mapping Lists.
Properties
in the parameter configuration. Example:
Other Object Classes
Please see Mapping Complex Objects for details on the strategy used to configure those kind of parameters.
Using Setters
You are not restricted to using private field mapping which is good if you are trying to make you Mojos resuable outside the context of Maven. Using the example above we could name our private fields using the underscore convention and provide setters that the configuration mapping mechanism can use. So our Mojo would look like the following:
Note the specification of the property name for each parameter which tells Maven what setter and getter to use when the field’s name does not match the intended name of the parameter in the plugin configuration.
В моем Dojo есть Mojo (Как написать плагин Maven)
Я был до моих подмышек, связанных с использованием Maven на работе. Для большого числа разработчиков я услышу «Ну и что?» Разница в том, что я обычно работаю в среде, где у меня нет прямого доступа к Интернету. Поэтому, когда я говорю, что много использую Maven, это что-то значит.
Зависимость ада
Чтобы быть справедливым, я использовал Maven случайно в моих примерах. Я обнаружил, что удобнее загружать зависимости и избегать «ада зависимостей». Ситуация, когда я должен загрузить библиотеку для библиотеки, которую я использую. Например, необходимо загрузить Hamcrest, чтобы использовать JUnit. Дома вставьте зависимость для JUnit, и Maven загрузит Hamcrest для меня, потому что это зависимость от JUnit. Если бы была зависимость от Хэмкреста, Мэйвен тоже загрузил бы это. Когда я на работе, мне нужно исследовать, какие зависимости есть у JUnit, а затем исследовать, какие есть зависимости. Я избегал использования библиотек из-за этой самой ситуации.
Ситуации меняются
Изменение связано с тем, что я использую Spring Roo на работе. Roo использует Maven для управления зависимостями Spring, которые он должен включить. Из-за этого изменения я настроил сервер Nexus в сети разработки и начал процесс переноса зависимостей из Интернета в сеть разработки. Это заставило меня узнать о Maven.
Что я узнал о Maven
Maven — плагин, богатый
Maven основан на архитектуре плагинов. Все, что делает что-то в Maven, является плагином. Это идет от основной функциональности как компиляция к созданию сайтов. Как можно себе представить, каждый плагин имеет определенные общие черты.
Maven ориентирован на пакет, жизненный цикл, фазу и цель
Maven известен тем, что он встраивает что-то в какой-то упакованный предмет, например, файл jar. Это очевидно, это одна из первых строк файла pom. Что может быть неизвестно, так это то, что существует ряд «фаз» или «жизненных циклов», которые выполняют сборку пакета (посмотрите, что я там делал). Фактически, один из этих этапов называется «упаковка». Список фаз по умолчанию в жизненном цикле выглядит следующим образом:
В сборке Maven много чего происходит! Все это выполняется каким-то плагином. Каждый плагин состоит из целей, которые можно настроить на определенную фазу жизненного цикла. Например, цель jar maven-jar-plugin настроена на запуск в фазе пакета.
Создание плагина
Теперь, когда у вас есть более глубокие знания о том, что происходит в сборке, пришло время объяснить, что необходимо для создания плагина Maven.
Плагины полны моджо
Что такое моджо? Mojo — сокращение от Maven, равнина Old Java Objects Это самая маленькая единица в плагине, который распознает Maven. Все плагины сделаны из моджо. Каждое моё связано с целью. Поэтому для того, чтобы плагин имел несколько целей, ему нужно несколько моджо. В примере, который я покажу, к сожалению, есть только одно моджо, но в этом примере также будут показаны лучшие методы тестирования плагина.
Лучшие практики — единственные допустимые практики
Посмотрите, что я сделал там, чтобы связать сделку с додзё в названии? Существует соглашение об именовании, модульное тестирование и интеграционное тестирование, связанные с написанием плагинов, если таковые имеются. Соглашение об именах является наиболее важным, так
Что в имени?
Модульное тестирование
Автоматизированное модульное и интеграционное тестирование также важно. Модульное тестирование следует немного другому шаблону каталога, чем обычное модульное тестирование, поэтому держитесь
Структура каталога при выполнении модульного теста плагина
Обратите внимание, что все тестовые каталоги организованы в тестовом каталоге. То, что вы делаете, это маленькая версия проекта, которая будет использовать плагин. Под каталогом ресурсов тестирования находится каталог модулей, за которым следует имя модуля в дочернем каталоге. Цель состоит в том, чтобы протестировать один модж за раз. Поскольку в моем примере есть только один модж, я настроил только один тест. Существуют и другие отличия, кроме настройки каталога, но они будут рассмотрены в разделе примеров.
Интеграционное тестирование
Я обнаружил, что это тестирование позволит узнать больше о конкретном плагине и о том, как он работает. Цель состоит в том, чтобы протестировать определенную ситуацию, как если бы она была частью реальной сборки проекта. Когда я имею в виду фактическую сборку проекта, я имею в виду, что существует даже временное хранилище только для интеграционной сборки. После прочтения о том, как настроить тесты, я много позаимствовал из настроек интеграционного теста spring-boot-maven-plugin и файлов mini-pom. Хорошо, я скопировал некоторые файлы в мой пример кода. Просто сообщаю, что Spring Boot сделал все правильно. Просто будьте в безопасности клон только для чтения или разветвите их код, чтобы быть в безопасности. Структура каталогов показана ниже.
Интеграционные тесты расположены не под каталогом test, а непосредственно под каталогом src в каталоге it. Я мог бы сделать больше интеграционных тестов, но сейчас достаточно одного.
пример
Пример плагина был вдохновлен тем фактом, что я рассеян и мне нужно напоминать обо всем, что я делаю. Я подумал о создании плагина wash-the-dogs-напоминалки-мавена, но я выбрал простой плагин напоминания-мейвена, потому что тогда я мог использовать его, чтобы напомнить мне обо всем, что мне нужно было сделать.