Краткое руководство по Maven Wrapper
1. Обзор
В этой быстрой статье мы покажем, как настроить Maven Wrapper для существующего проекта Maven.
2. Настройка Maven Wrapper
2.1. Плагин
Давайте воспользуемся этим плагином Maven Wrapper для автоматической установки в простом проекте Spring Boot.
Для начала нам нужно зайти в основную папку проекта и запустить эту команду:
Мы также можем указать версию Maven:
Параметр -N означает –нерекурсивный, так что оболочка будет применяться только к основному проекту текущего каталога, а не к каким-либо подмодулям.
После выполнения цели у нас будет больше файлов и каталогов в проекте:
2.2. Руководство
При ручном подходе мы можем копировать файлы и папки, показанные выше, из другого проекта в основную папку текущего проекта.
Например, в нашем файле свойств есть следующая строка:
Следовательно, будет загружена и использована версия 3.5.2.
3. Примеры использования
Оболочка должна работать с разными операционными системами, такими как:
После этого мы можем выполнить наши цели для системы Unix следующим образом:
И следующая команда для Batch:
Запустим наш проект Spring-Boot:
Результат такой же, как и для полностью установленного Maven:
Примечание: мы используем исполняемый файл mvnw вместо mvn, который теперь обозначен как программа командной строки Maven.
4. Вывод
В этом руководстве мы увидели, как настроить и использовать Maven Wrapper в проекте Maven.
Как всегда, исходный код этой статьи можно найти на GitHub.
Maven Wrapper
The Maven Wrapper is an easy way to ensure a user of your Maven build has everything necessary to run your Maven build.
Why might this be necessary? Maven to date has been very stable for users, is available on most systems or is easy to procure: but with many of the recent changes in Maven it will be easier for users to have a fully encapsulated build setup provided by the project. With the Maven Wrapper, this is very easy to do and it’s a great idea borrowed from Gradle.
The easiest way to setup the Maven Wrapper for your project is to use the Maven Wrapper Plugin with its provided wrapper goal. To add or update all the necessary Maven Wrapper files to your project execute the following command:
Normally you instruct users to install a specific version of Apache Maven, put it on the PATH and then run the mvn command like the following:
But now, with a Maven Wrapper setup, you can instruct users to run wrapper scripts:
A normal Maven build will be executed, with the one important change that if the user doesn’t have the necessary version of Maven specified in .mvn/wrapper/maven-wrapper.properties it will be downloaded for the user first, installed and then used.
Subsequent uses of mvnw/mvnw.cmd use the previously downloaded, specific version as needed.
Supported Systems
The wrapper should work on various operating systems including
For all those *nix operating systems, various shells should work including
In terms of Apache Maven versions itself, the wrapper should work with any Maven 3.x version and it defaults to the release used when setting up the wrapper. We do NOT plan to support the deprecated, EOL’ed Maven 2.x.
The maven-wrapper.jar (to download and install target Maven version required by mvnw) and the Maven Wrapper Plugin (to inject Wrapper into a project) use Java 7.
Verbose Mode
The wrapper supports a verbose mode in which it outputs further information. It is activated by setting the MVNW_VERBOSE environment variable to true.
By default it is off.
Usage without Binary JAR
By default, the Maven Wrapper JAR archive is added to the using project as small binary file .mvn/wrapper/maven-wrapper.jar. It is used to bootstrap the download and invocation of Maven from the wrapper shell scripts.
If your project is not allowed to contain binary files like this, you can configure your version control system to exclude checkin/commit of the wrapper jar.
If the JAR is not found to be available by the scripts they will attempt to download the file from the URL specified in .mvn/wrapper/maven-wrapper.properties under wrapperUrl and put it in place. The download is attempted via curl, wget and, as last resort, by compiling the ./mvn/wrapper/MavenWrapperDownloader.java file and executing the resulting class.
If your Maven repository is password protected you can specify your username via the environment variable MVNW_USERNAME and the password via the environment variable MVNW_PASSWORD.
Using a Different Version of Maven
To switch the version of Maven used to build a project, you can initialize it using:
which works for any version except snapshots. Once you have a wrapper you can change its version by setting the distributionUrl in .mvn/wrapper/maven-wrapper.properties, e.g.
Using Basic Authentication for Distribution Download
To download Maven from a location that requires Basic Authentication you have 2 options:
Set the environment variables MVNW_USERNAME and MVNW_PASSWORD
add user and password to the distributionUrl like that: distributionUrl=https://username:password@ /maven2/org/apache/maven/apache-maven/3.2.1/apache-maven-3.2.1-bin.zip
Specifying Maven Distribution Base Path
This is a feature of Maven itself and the wrapper just happens to take it into account. Simply set MAVEN_USER_HOME to the desired path and the wrapper uses it as the base of the Maven distro installation.
Using a Maven Repository Manager
When using an internal Maven repository manager, you have two options:
If MVNW_REPOURL is set during the wrapper installation with the maven-wrapper-plugin, the URL is used in the maven-wrapper.properties file.
If not set, but your mirror URL in your settings.xml is configured, it will be used.
Internals
Maven Wrapper is composed of 3 pieces:
maven-wrapper, providing the maven-wrapper.jar that downloads, installs and runs target Maven distribution,
maven-wrapper-plugin, the wrapper plugin to ease installing Wrapper into a project.
Copyright ©2016–2021 The Apache Software Foundation. All rights reserved.
Какова цель файлов mvnw и mvnw.cmd?
Когда я создавал приложение Spring Boot, я мог видеть mvnw и mvnw.cmd файлы в корне проекта. Какова цель этих двух файлов?
Это позволяет запускать проект Maven без установки и представления Maven на пути. Он загружает правильную версию Maven, если он не найден (насколько я знаю по умолчанию в вашем домашнем каталоге пользователя).
mvnw Файл для Linux (Баш) и mvnw.cmd для окружающей среды Windows.
Для создания или обновления всех необходимых файлов Maven Wrapper выполните следующую команду:
Чтобы использовать другую версию maven, вы можете указать версию следующим образом:
Команда mvnw использует Maven, который по умолчанию загружается
/.m2/wrapper при первом использовании.
Чтобы создать оболочку с нуля с помощью Maven (она должна быть PATH запущена:
mvnw: это исполняемый скрипт оболочки Unix, используемый вместо полностью установленного Maven
mvnw.cmd : это для среды Windows
Случаи использования
Оболочка должна работать с различными операционными системами, такими как:
После этого мы можем выполнить наши цели для системы Unix следующим образом:
И следующая команда для Batch:
Плагин Maven Wrapper
Плагин Maven Wrapper для автоматической установки в простом проекте Spring Boot.
Сначала нам нужно зайти в главную папку проекта и запустить эту команду:
Мы также можем указать версию Maven:
Takari: Maven на стероидах
Предыстория
Уже довольно давно я работаю в проекте, в котором используется система сборки Maven. По началу, когда проект был ещё не таких размеров как сейчас, время его полной компиляции было относительно разумным и не вызывало нареканий. Но со временем код разросся, количество подпроектов резко увеличилось и среднее время полной компиляции выросло до 6 — 10 минут. Что служило постоянным источником упрёков со стороны разработчиков.
Следует так же отметить. что мы не использовали параллельную сборку, т.к. это регулярно вызывало различные проблемы. То артефакты в локальном хранилище побьются, то просто соберёт не в том порядке и в финальный WAR артефакт попадёт старый, неперекомпилированный код. Конечно некоторые разработчики использовали параллельную сборку на свой страх и риск. Но рано или поздно попадали в ситуацию, когда не могли разобраться что происходит. И простая перекомпиляция в один поток сразу помогала.
Так продолжалось довольно долго, пока я не наткнулся на довольно любопытный сайт компании Takari, на котором предлагаются способы по усовершенствованию методов работы с Maven.
Забегая вперёд отмечу, что описываемые здесь инструменты не только решают проблему некорректной работы Maven, но и дают существенный прирост скорости сборки.
Concurrent Safe Local Repository
Данное усовершенствование предназначено для решения проблемы битых артефактов в локальном репозитарии.
Дело в том, что в Maven работа с локальным хранилищем (по сути каталогом на файловой системе) реализована непотокобезопасным способом. Т.е. если параллельно собирающиеся проекты начинают одновременно выкачивать одну и ту же зависимость, то в результате получается битый файл. Вот именно эту проблему и решает данное дополнение.
Для того, чтобы им воспользоваться, необходимо модифицировать непосредственно сам установленный Maven:
Всё. Больше никаких дополнительный действий не требуется. Теперь все операции с локальным репозитарием будут безопасными. Само по себе это расширение может использоваться разве что на серверах CI, когда множество сборок происходит одновременно и хочется использовать один репозитарий для экономии места. Но для рядового разработчика более интересно использование совместно со Smart Builder, который работает исходя из предположения, что данное расширение уже установлено.
Как показал опыт, при использовании этого решения сборка начинает работать чуть медленнее, но зато более надёжно.
Takari Smart Builder
Это расширение устанавливается аналогично предыдущему:
И обеспечивает более продвинутый алгоритм распараллеливания сборки проектов Maven. Разница в работе стандартного планировщика сборки Maven и Smart Builder иллюстрирует диаграмма ниже:
Стандартная стратегия распараллеливания Maven проста и наивна. Она базируется на вычислении глубины зависимостей. Maven запускает параллельную сборку всех проектов одного уровня, пока они не закончатся и только потом переходит на следующий уровень.
Takari Smart Builder, в свою очередь, использует более продвинутую стратегию. Он вычисляет цепочки зависимостей, производит топологическую сортировку и только после этого принимает решение о том, в какой последовательности необходимо производить сборку проектов.
Более того. В процессе компиляции, он запоминает время компиляции каждого проекта в файл .mvn/timing.properties и использует его как дополнительную информацию для того, чтобы в следующий раз завершить компиляцию как можно быстрее.
Для того, чтобы воспользоваться этим функционалом, необходимо при запуске Maven указать дополнительный ключ. Например:
Всё становится проще с Maven 3.3.1
В версии Maven 3.3.1 было реализовано несколько нововведений. Первое и самое главное — возможность объявлять расширения ядра Maven прямо в проекте. Для этого нужно добавить файл .mvn/extensions.xml. В приложении к описанному раньше, этот файл может иметь следующий вид:
Теперь нам не нужно докладывать библиотеки непосредственно в дистрибутив Maven. При этом мы получаем тот же результат.
Файл extensions.xml — не единственный возможный в каталоге .mvn. Тут могут располагаться ещё два файла: jvm.config и maven.config.
jvm.config содержит параметры JVM для запуска компиляции текущего проекта. Например этот файл может выглядеть следующим образом:
Первая опция задаёт размер heap равный 2 Гб, а следующие две — оптимизируют работу JVM под нужды Maven (подсмотрено тут).
maven.config — ещё один файл с параметрами, но на этот раз для самого Maven. Например:
Таким образом мы можем задать, что по умолчанию используется smart builder с количеством потоков равному количеству логических ядер. Т.е., если мы просто выполним
Тут, правда есть один нюанс. Т.к. сборка идёт в несколько потоков, то и лог сборки выводится этими потоками конкурентно. В результате, при возникновении проблем, не всегда бывает понятно что происходит, в следствии того, что строчки оказываются перемешанными. В этом случае, если хочется запустить сборку в один поток и разобраться в причинах неприятностей, то приходится уже вручную переключать сборку в однопоточный режим:
The Takari Lifecycle
The Takari Lifecycle — альтернатива жизненному циклу Maven по умолчанию (сборка JAR файлов). Его отличительная особенность — вместо пяти отдельных плагинов для одного стандартного жизненного цикла используется один универсальный с тем же функционалом, но с гораздо меньшим количеством зависимостей. Как следствие — гораздо более быстрый старт, более оптимальная работа и меньшее потребление ресурсов. Что даёт существенный прирост производительности при компиляции сложных проектов с большим количеством модулей.
Для активации модернизированного жизненного цикла необходимо добавить takari-lifecycle-plugin в качестве расширения сборки:
А так же переопределить сборку JAR модулей как takari-jar:
После этого все проекты типа POM, а так же takari-jar проекты будут собираться с использование нового жизненного цикла.
Так же можно включить данный жизненный цикл для всех JAR модулей (см. документацию), в нашем случае это начало приводить к конфликтам с различными плагинами Maven. В результате было принято решение просто переопределить packaging модулей, где это можно сделать без ущерба для сборки. Как показала практика этого оказалось более чем достаточно.
Следует так же отметить, что при использование расширения takari-lifecycle-plugin, изменяется расположение различных настроек сборки. Они перемещаются в секцию configuration этого плагина. Например:
Более подробную информацию можно посмотреть в документации..
Takari Maven Wrapper
У Takari есть ещё одна приятная вещь — Maven Wrapper. По аналогии с Gradle Wrapper, он позволяет запустить сборку проекта сразу после клонирования. Без необходимости установки и настройки Maven у себя на компьютере. К тому же, это позволяет закрепить необходимую версию Maven за проектом.
Самый простой способ добавить в свой проект враппер — воспользоваться архетипом. Выполним в корне проекта:
После этого в текущем каталоге у нас появятся два скрипта:
Всё. После этого можно вызывать:
А если требуется другая версия Maven, то можно установить необходимый URL в конфигурации .mvn/wrapper/maven-wrapper.properties.
И опять-таки тут не обходится без нюансов. Так в организациях с закрытой сетью часто используют проксирующие репозитарии Maven такие как Nexus или Artifactory. В таком случае каждый разработчик вынужден отдельно настраивать у себя зеркало (mirror) Maven на этот репозитарий. Что немного противоречит идеологии враппера — отсутствие необходимости каких либо настроек.
Выйти из положения можно следующим образом: создадим в нашем проекте файл .mvn/settings.xml вида
и добавим в файл .mvn/maven.config строчку
В результате чего зеркало начнёт подхватываться автоматически.
Тестирование и результаты
Всё вышеописанное не имело бы смысла, если бы не давало впечатляющих результатов по ускорению сборки проекта. И чтобы не быть голословным — приведу результаты, которые были получены на одном из наших рабочих проектов.
Все промежуточные результаты сведены в таблицу ниже:
| Как собиралось | Количество потоков | Затраченное время |
|---|---|---|
| default | 1 | 5:32 |
| default | 4 | 3:25 |
| smart build | 4 | 3:18 |
| smart build + takari-jar | 1 | 3:23 |
| smart build + takari-jar | 4 | 1:33 |
Smart Build запускался по два раза, и фиксировался второй результат, т.к. после первого запуска может происходить оптимизация порядка выполнения сборки (см. документацию).
Что любопытно, добавление Takari Lifecycle в однопоточном режиме даёт такой же прирост производительности, как и выполнение сборки в 4-е потока но на «ванильном» Maven.
В качестве заключения
Я только недавно обнаружил инструменты описанные в данной статье. Так что практика их использования пока ещё очень скромная. Возможно со временем ещё вылезут какие-либо подводные камни. Но в любом случае такого радикального ускорения сборки оказалось достаточным, чтобы рискнуть использовать эти возможности в нашем тех процессе. Время покажет что из этого получится.
Так же хочу обратить внимание, что в github репозитарии компании Takari есть ещё некоторое количество любопытных проектов. Их описание выходит за рамки данной статьи, но, возможно, кого-то что-то ещё и заинтересует.
Как уже отметил в комментариях, начал приходить фидбэк от разработчиков. Оказалось, что файл mvnw.bat не выполняет свои функции. Была внесена правка на скорую руку, которая привела функционал в надлежащий вид:
Так же оказалось, что в целом сборка под Windows значительно медленнее, чем под Linux. Счем это связано пока не понятно.
Всплыл ещё один тонкий момент. Сборка для SonarQube конфликтует со Smart Builder’ом. Т.к. по умолчанию включена опция —builder smart, то для сборки под SonarQube не достаточно выполнить
Нужно ещё и переключиться обратно на стандартную стратегию сборки:
Для чего нужны файлы mvnw и mvnw.cmd?
Когда я создал приложение Spring Boot, я мог видеть файлы mvnw и mvnw.cmd в корне проекта. Какова цель этих двух файлов?
4 ответа
Эти файлы взяты из оболочки Maven. Он работает аналогично оболочке Gradle.
Это позволяет вам запускать проект Maven без установки и присутствия Maven в пути. Он загружает правильную версию Maven, если она не найдена (насколько мне известно, по умолчанию в домашнем каталоге вашего пользователя).
Чтобы создать или обновить все необходимые файлы Maven Wrapper, выполните следующую команду:
Чтобы использовать другую версию maven, вы можете указать версию следующим образом:
Команда mvnw использует Maven, который по умолчанию загружается в
/.m2/wrapper при первом использовании.
Чтобы сгенерировать оболочку с нуля с помощью Maven (она должна быть уже запущена PATH ):
mvnw: это исполняемый сценарий оболочки Unix, используемый вместо полностью установленного Maven.
mvnw.cmd : для среды Windows.
Примеры использования
Оболочка должна работать с разными операционными системами, такими как:
После этого мы можем выполнить наши цели для системы Unix следующим образом:
И следующая команда для Batch:
Плагин Maven Wrapper
плагин Maven Wrapper для автоматической установки в простом проекте Spring Boot.
Для начала нам нужно зайти в основную папку проекта и запустить эту команду:
Мы также можем указать версию Maven:




