Maven плагины для сборки проекта

С описанием фреймворка maven можно познакомиться здесь. На этой странице рассматриваются наиболее распространенные плагины, используемые при сборке проекта. Список установленных на компьютере плагинов maven можно увидеть в директории ${M2_HOME}/repository/org/apache/maven/plugins приблизительно в таком виде, как на следующем скриншоте.

На странице рассмотрены следующие плагины с примерами :

Плагин создания проекта maven-archetype-plugin

Одним из самых первых плагинов, с которым приходится знакомиться или начинать новый проект, это maven-archetype-plugin. Данный плагин позволяет по определенному шаблону (archetype) сформировать структуру проекта. Примеры maven проектов для разнотипных приложений можно увидеть здесь.

Плагин компиляции maven-compiler-plugin

Самый популярный плагин, позволяющий управлять версией компилятора и используемый практически во всех проектах, это компилятор maven-compiler-plugin. Он доступен по умолчанию, но практически в каждом проекте его приходится переобъявлять. В простейшем случае плагин позволяет определить версию java машины (JVM), для которой написан код приложения, и версию java для компиляции кода. Пример использования :

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
        <source>1.7</source>
        <target>1.7</target>
        <encoding>UTF-8</encoding>
    </configuration>
</plugin>

В данном примере определена версия java-кода 1.7, на котором написана программа (source). Версия java машины, на которой будет работать программа, определена тегом <target>. В теге <encoding> указана кодировка исходного кода (UTF-8). По умолчанию используется версия java 1.3, а кодировка выбирается из операционной системы. Плагин позволяет указать путь к компилятору javac тегом <executable>.

Плагин maven-compiler-plugin имеет две цели :

  • compiler:compile - компиляция исходников, по умолчанию связана с фазой compile;
  • compiler:testCompile - компиляция тестов, по умолчанию связана с фазой test-compile.

Кроме приведёных настроек компилятор позволяет определить аргументы компиляции :

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
        <compilerArgs>
            <arg>-verbose</arg>
            <arg>-Xlint:all,-options,-path<arg>
        </compilerArgs>
    </configuration>
</plugin>

Плагин позволяет даже выполнить компилирование не-java компилятором :

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
        <compilerId>csharp</compilerId>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>org.codehaus.plexus</groupId>
            <artifactId>plexus-compiler-csharp</artifactId>
            <version>1.6</version>
        </dependency>
    </dependencies>
</plugin>

Плагин копирования ресурсов maven-resources-plugin

Перед сборкой проекта необходимо все ресурсы (файлы изображений, файлы .properties) скопировать в директорию target. Для этого используется плагин maven-resources-plugin. Пример использования плагина :

<plugin>
    <artifactId>maven-resources-plugin</artifactId>
    <version>2.6</version>
    <executions>
        <execution>
            <id>copy-resources</id>
            <phase>validate</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <outputDirectory>
                       ${basedir}/target/resources
                </outputDirectory>
                <resources>
                    <resource>
                        <directory>src/main/resources/props</directory>
                        <filtering>true</filtering>
                        <includes>
                            <include>**/*.properties</include>
                        </includes>
                    </resource>
                    <resource>
                        <directory>src/main/resources/images</directory>
                        <includes>
                            <include>**/*.png</include>
                        </includes>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>

Тег <outputDirectory> определяет целевую директорию, в которую будет происходить копирование.

В данном примере maven должен положить в директорию target всё точно также, как и было в проекте. При копировании ресурсов можно использовать дополнительные возможности maven-resources-plugin, позволяющие вносить изменения в файлы свойств. Для этого используется тег <filtering>, который при значении true предлагает плагину заглянуть во внутрь файла и при наличии определенных значений заменить их переменными maven'а. Файлы изображений не фильтруются. Поэтому ресурсы можно разнести по разным тэгам <resource />.

Дополнительно об использовании фильтрации для корректировки значений в файле свойств .properties можно почитать здесь.

Плагин включения исходных кодов maven-source-plugin

Плагин maven-source-plugin позволяет включать в сборку проекта исходный код. Данная возможность особенно полезна, если создается многомодульная архитектура проекта, включающая различные файлы .jar, и требуется отладка отдельных частей. Пример использования maven-source-plugin :

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-source-plugin</artifactId>
    <version>2.2.1</version>
    <executions>
        <execution>
            <id>attach-sources</id>
            <phase>verify</phase>
            <goals>
                <goal>jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

В данном примере в релиз проекта будут включены исходные коды программы.

Плагин копирования зависимостей maven-dependency-plugin

Для копирования зависимостей в директорию сборки используют плагин maven-dependency-plugin. Пример копирования библиотек в директорию ${project.build.directory}/lib :

<plugin> 
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.5.1</version>
    <configuration>
        <outputDirectory>
            ${project.build.directory}/lib/
        </outputDirectory>
        <overWriteReleases>false</overWriteReleases>
        <overWriteSnapshots>false</overWriteSnapshots>
        <overWriteIfNewer>true</overWriteIfNewer>
    </configuration>
    <executions>
        <execution> 
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Назначение опций :

  • outputDirectory - определение директории, в которую будут копироваться зависимости;
  • overWriteReleases - флаг необходимости перезаписывания зависимостей при создании релиза;
  • overWriteSnapshots - флаг необходимости перезаписывания неокончательных зависимостей, в которых присутствует SNAPSHOT;
  • overWriteIfNewer - флаг необходимости перезаписывания библиотек с наличием более новых версий.

По умолчанию <overWriteReleases> и <overWriteSnapshots> - false, для <overWriteIfNewer> - true.

В примере определен раздел <execution> с идентификатором copy-dependencies - копирование зависимостей. Плагин используется в фазе сборки <package>, цель copy-dependencies. В разделе конфигурации configuration определен каталог, в который будут копироваться зависимости. Дополнительные параметры говорят о том, что перезаписываем библиотеки с наличием более новых версий, не перезаписываем текущие версии и не перезаписываем зависимости без окончательной версии (SNAPSHOT).

Плагин maven-dependency-plugin включает несколько целей, некоторые приведены ниже :

  • mvn dependency:analyze - анализ зависимостей (используемые, неиспользуемые, указанные, неуказанные);
  • mvn dependency:analyze-duplicate - определение дублирующиеся зависимостей;
  • mvn dependency:resolve - разрешение (определение) всех зависимостей;
  • mvn dependency:resolve-plugin - разрешение (определение) всех плагинов;
  • mvn dependency:tree - вывод на экран дерева зависимостей.

Плагин создания jar-файла maven-jar-plugin

Плагин maven-jar-plugin позволяет сформировать манифест, описать дополнительные ресурсы, необходимые для включения в jar-файл, и упаковать проект в jar-архив. Пример проектного файла pom.xml, описывающий настройку данного плагина :

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
        <includes>
            <include>**/properties/*</include>
        </includes>
        <excludes>
            <exclude>**/*.png</exclude>
        </excludes>
        <archive>
           <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
        </archive>
    </configuration>
</plugin>

В примере определена директория и манифест, включаемые в сборку. Тегом <excludes> блокируется включение в сборку определенных файлов изображений.

Плагин maven-jar-plugin может создать и включить в сборку MANIFEST.MF самостоятельно. Для этого следует в секцию <archive> включить тег <manifest> с опциями :

<configuration>
    <archive>
        <manifest>
            <addClasspath>true</addClasspath>
            <classpathPrefix>lib/</classpathPrefix>
            <mainClass>ru.company.AppMain</mainClass>
        </manifest>
    </archive>
</configuration>

Опции тега <manifest> :

  • <addClasspath> определяет необходимость добавления в манифест CLASSPATH;
  • <classpathPrefix> позволяет дописывать префикс (в примере lib) перед каждым ресурсом;
  • <mainClass> указывает на главный исполняемый класс.

Определение префикса в <classpathPrefix> позволяет размещать зависимости в отдельной папке.

Пример создания сборки (исполняемый jar-файл) с зависимостями библиотеки SWT можно посмотреть здесь.

Плагин тестирования maven-surefire-plugin

Плагин maven-surefire-plugin предназначен для запуска тестов и генерации отчетов по результатам их выполнения. По умолчанию на тестирование запускаются все java-файлы, наименование которых начинается с «Test» и заканчивается «Test» или «TestCase» :

  • **/Test*.java
  • **/*Test.java
  • **/*TestCase.java

Если необходимо запустить java-файл с отличным от соглашения наименованием, например Sample.java, то необходимо в проектный файл pom.xml включить соответствующую секцию с плагином maven-surefire-plugin.

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.12.4</version>
        <configuration>
            <includes>
                <include>Sample.java</include>
            </includes>
        </configuration>
    </plugin>
</plugins>

Плагин maven-surefire-plugin содержит единственную цель surefire:test. Для разработки кодов тестирования можно использовать как JUnit, так и TestNG. Результаты тестирования в виде отчетов в форматах .txt и .xml сохраняются в директории ${basedir}/target/surefire-reports.

Иногда приходится отдельные тесты исключать. Это можно сделать включением в секцию <configuration> тега <excludes>.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.12.4</version>
    <configuration>
        <excludes>
            <exclude>**/TestCircle.java</exclude>
            <exclude>**/TestSquare.java</exclude>
        </excludes>
    </configuration>
</plugin>

Чтобы запустить проект на тестирование необходимо выполнить одну из следующих команд :


mvn test

mvn -Dmaven.surefire.debug test
 

Чтобы пропустить выполнение тестов на этапе сборки проекта, можно выполнить команду.


mvn clean package -Dmaven.test.skip=true
 

Также можно проигнорировать выполнение тестирования проекта включением в секцию <configuration> тега <skipTests>

<configuration>
    <skipTests>true</skipTests>
</configuration>

Плагин генерации номера сборки buildnumber-maven-plugin

Предположим, что нам нужно в манифест MANIFEST.MF нашего WEB-приложения и в файл свойств src/main/resources/app.properties положить номер сборки, который определяется переменной ${buildNumber}. Файл манифеста будем генерить автоматически. А в файл свойств проекта app.properties включим параметры, значения которых будут определяться на этапе сборки проекта :

# application.properties
app.name=${pom.name}
app.version=${pom.version}
app.build=${buildNumber}

В режиме выполнения программы (runtime) можно обращаться к данному файлу свойств для получения наименования приложения и номера версии сборки.

Для генерирования уникального номера сборки проекта используется плагин buildnumber-maven-plugin. Найти плагин можно в репозитории в директории ${M2_HOME}/repository/org/codehaus/mojo. Пример настройки плагина в проектном файле pom.xml :


<modelVersion>4.0.0</modelVersion>
<groupId>ru.hellogwt.sample</groupId>
<artifactId>hellogwt</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<name>GWT Maven Archetype</name>
. . . .
<plugins>
    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>buildnumber-maven-plugin</artifactId>
        <version>1.2</version>
        <executions>
            <execution>
                <phase>validate</phase>
                <goals>
                    <goal>create</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <revisionOnScmFailure>true</revisionOnScmFailure>
            <format>{0}-{1,date,yyyyMMdd}</format>
               <items> 
                 <item>${project.version}</item>
                 <item>timestamp</item>
               </items>
        </configuration>
    </plugin>
</plugins>

В приведенном примере плагин запускается во время фазы жизненного цикла validate и генерирует номер версии ${buildNumber}, который собирается из нескольких частей и определен тэгом <format />. Каждая часть номера версии заключается в фигурные скобки и формируется согласно описанию MessageFormat языка Java. Каждой части соответствует тэг <item />, указывающий, какое значение должно быть подставлено.

Если в pom.xml не настроена работа с SCM (Source Code Management) типа Subversion, Git и т.п., то при попытке генерации номера сборки будет получено сообщение об ошибке "The scm url cannot be null". В этом случае можно указать в pom.xml заглушку SCM.

<scm>
    <connection>scm:svn:http://127.0.0.1/dummy</connection>
    <developerConnection>scm:svn:https://127.0.0.1/dummy</developerConnection>
    <tag>HEAD</tag>
    <url>http://127.0.0.1/dummy</url>
</scm>

Чтобы номер сборки генерировался независимо от подключения к SCM в настройках конфигурации плагина следует указать свойство revisionOnScmFailure равным true.

Теперь настроим плагин maven-war-plugin, чтобы номер версии поместить в MANIFEST.MF, который будет создаваться автоматически :

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.6</version>
    <configuration>
        <archive>
            <manifest>
                <addDefaultImplementationEntries>
                    true
                </addDefaultImplementationEntries>
            </manifest>
            <manifestEntries>
                <Implementation-Build>
                    ${buildNumber}
                </Implementation-Build>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

Генерируемое значение, по-умолчанию, сохраняется в файле ${basedir}/buildNumber.properties и имеет имя buildNumber. При необходимости данные параметры могут быть переопределены через свойства buildNumberPropertiesFileLocation и buildNumberPropertyName соответственно.

Чтобы определить значения в файле свойств src/main/resources/app.properties включим фильтрацию ресурсов в разделе <build> :

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
     ....
</build>

Дополнительную информацию о фильтрации для корректировки значений в файле свойств *.properties можно почитать здесь.

После выполнения сборки проекта манифест MANIFEST.MF в файле .war будет иметь приблизительно следующий вид :

Manifest-Version: 1.0
Implementation-Title: GWT Maven Archetype
Implementation-Version: 1.0
Implementation-Vendor-Id: ru.hellogwt.sample
Built-By: Father
Build-Jdk: 1.7.0_67
Created-By: Apache Maven 3.3.9
Implementation-Build: 1.0-20161001
Archiver-Version: Plexus Archiver

Конечно же изменится и файл свойств app.properties в сборке :

# application.properties
app.name=GWT Maven Archetype
app.version=1.0
app.build=1.0-20161001

Чтобы в сервлете WEB-приложения прочитать версию сборки в файле MANIFEST.MF можно использовать следующий код :

import java.io.IOException;
import java.util.Properties;
...
String version = "UNDEFINED"; 
Properties prop = new Properties();
try {
    prop.load(getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF"));
    version = prop.getProperty("Implementation-Build");
} catch (IOException e) {}
...
  Рейтинг@Mail.ru