Статьи

Несколько дополнений к вашей сумке Maven-Fu

Apache Maven прост, но довольно мощный; С помощью нескольких хитростей вы можете значительно упростить и оптимизировать свой опыт разработки.

Работа с несколькими неколокационными модулями

Скажем, у вас есть два служебных модуля foo и bar из одного мастер-проекта A и другого проекта B который использует foo и bar .

Работая над B , вы понимаете, что вам нужно время от времени делать некоторые изменения для foo и bar ; однако, поскольку они находятся в другом проекте, вам обычно нужно

  • переключиться на A
  • внести изменения
  • mvn install
  • переключиться обратно на B
  • и «обновить» зависимости (если вы используете IDE).

Каждый раз , когда необходимо внести изменения в основной поток.

В Maven вместо этого вы можете временно «объединить» три части с помощью фиктивного главного POM, который определяет foo , bar и B как дочерние модули:

01
02
03
04
05
06
07
08
09
10
    <modelVersion>4.0.0</modelVersion>
    <!-- blah blah blah -->
 
    <modules>
        <module>foo</module>
        <module>bar</module>
        <module>B</module>
    </modules>

Что это значит для меня?

IDE (например, IntelliJ IDEA ) будут определять корень как многомодульный проект; Это означает, что вы сможете:

  • плавно переходить от одного модуля к другому. Нет больше декомпиляции, несовместимости байт-кода или исходных карт ; удобно, когда вы ищете использование какого-либо класса или метода — или рефакторинг — в рамках вашего «составного» проекта.
  • изменять источники и ресурсы каждого модуля по требованию в одном и том же окне проекта. Среда IDE автоматически перекомпилирует изменения и добавит все в путь к классам среды выполнения; удобно для тестирования и отладки в IDE с возможностью горячей перезагрузки .
  • Версия без проблем. Если эти три модуля находятся под разными корнями VCS, IDE, такие как IDEA, будут отслеживать каждый репо в отдельности; если вы фиксируете один набор изменений, у каждого репо будет новый коммит, отражающий его собственную часть изменения; все с одинаковым сообщением!

Между тем, обычный Maven будет строить foo / bar (как требуется) и B в правильной последовательности, если корневой модуль собран — именно то, что мы хотели бы.

Относительные пути, FTW!

Даже если модули разбросаны по всей файловой системе, Maven может легко разрешить их с помощью относительных путей:

1
2
3
4
5
<modules>
        <module>../foo</module>
        <module>grandpa/papa/bar</module>
        <module>../../../../../media/disk2/repos/top-secret/B</module>
    </modules>

Брось это clean

Пожалуй, наиболее используемая (и, следовательно, наиболее часто используемая ) команда Maven:

1
mvn clean install

Фактически запускается сразу после внесения изменений в ваш проект.

И для большинства сценариев это сильно излишне.

С нуля?

Команда объединяет две фазы жизненного цикла — «стадии» процесса сборки Maven. Фазы имеют определенную последовательность; поэтому, если вы запрашиваете какую-либо фазу для запуска, все предыдущие фазы в ее жизненном цикле будут выполняться до нее. Но плагины Maven достаточно умны, чтобы пропустить свою работу, если обнаружат, что им нечего делать; например, компиляция не произойдет, если скомпилированные классы будут обновлены.

Теперь clean не является частью жизненного цикла по умолчанию ; скорее это используется, чтобы начаться с нуля, удаляя весь target каталог. С другой стороны, install — это почти конец строки (непосредственно перед deploy в жизненном цикле по умолчанию).

mvn clean install запустит обе эти фазы; и, благодаря clean , все между ними также .

Это удобно, когда вы хотите очистить все и получить последние артефакты, установленные в вашем локальном репозитории Maven. Но в большинстве случаев вам не нужно все это.

Кроме того, install конечном итоге загромождает ваш локальный кеш Maven; особенно если вы делаете частые снимки / выпуски с пакетами размером MB или GB.

Быть ленивым; делай только то, что нужно!

Maven-фу

Если вы обновили один исходный файл и хотите распространить его в каталог target/classes :

1
mvn compile

где Maven автоматически обнаружит любые изменения и полностью пропустит компиляцию, если их нет.

Если изменение было в тестовом классе или ресурсе:

1
mvn test-compile

получит его в target/test-classes .

Просто для запуска тестов (которые автоматически скомпилируют любые грязные исходные / тестовые классы):

1
mvn test

Чтобы получить копию окончательного комплекта в target :

1
mvn package

Как вы часто можете начать с чистого листа перед упаковкой:

1
mvn clean package

Аналогично, просто укажите конечную фазу; или и начальную, и конечную цели, если вы хотите очиститься до некоторой степени. Вы сэкономите много времени, вычислительной мощности и характера.

Тем временем в производстве …

Если ваша текущая сборка будет запущена в производство, просто забудьте большинство из вышеперечисленных;)

1
mvn clean package

Хотя любая из «подкоманд» теоретически должна делать то же самое, вы не хотите рисковать;)

Хотя я использую package выше, в некотором смысле install может быть лучше; потому что тогда у вас будет копия рабочего артефакта в вашем .m2/repository — это может быть спасением, если вы потеряете доставленную / развернутую копию.

Больше пропусков …

--no-snapshot-updates

Если вы внимательно наблюдали за сборкой, включающей зависимости моментальных снимков , вы бы заметили, что поиск файлов метаданных Maven для моментальных снимков занимает несколько секунд (и, в конце концов, приводит к сбою предупреждений; если у вас нет привычки публиковать артефакты моментальных снимков для дистанционный пульт).

Обычно это бесполезно, если вы также строите зависимости моментальных снимков локально, поэтому вы можете отключить проверку метаданных (и попытку синхронизации моментальных снимков) с помощью параметра --no-snapshot-updates или -nsu .

Конечно, -o предотвратит все удаленные синхронизации; но вы не можете использовать его, если вы действительно хотите -nsu некоторые зависимости, в этом случае -nsu поможет.

Вы можете пропустить компиляцию!

Как и (в) известном -Dmaven.test.skip — или -DskipTests , вы можете пропустить этап компиляции (даже если есть изменения кода) через -Dmaven.main.skip . Удобно, когда вы просто хотите запускать тесты, не занимаясь компиляцией; если вы знаете, что материал уже скомпилирован, конечно. Так же, как -DskipTests — но наоборот!

(Слава этому посту )

Maven-фу

Продолжение: -rf

Возможно, вы уже знаете, что, если модуль выходит из строя в середине сборки, вы можете возобновить сборку с этой точки с помощью параметра -rf :module-name .

Этот параметр также работает на ровном месте; это не ограничено сценариями отказа. Если у вас 30 модулей, но вы просто хотите собрать последние 5, просто запустите с -rf :name-of-26th-module .

Вкусные приемы тестирования

Наследование тестов

Обычно артефакты Maven не включают тестовые классы / ресурсы. Но есть случаи, когда вы хотите наследовать некоторые базовые тестовые классы в дочерние модули. С помощью спецификатора test-jar вы можете наследовать артефакт, который содержит только тестовые классы и ресурсы:

1
2
3
4
5
6
7
<dependency>
            <groupId>com.acme</groupId>
            <artifactId>foo</artifactId>
            <version>3.2.1</version>
            <type>test-jar</type>
            <scope>test</scope>
        </dependency>

Соответствующая конфигурация сборки в «зависимом» модуле будет выглядеть так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>test-jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

Одно предостережение заключается в том, что переходные тестовые зависимости не наследуются в этом процессе, и их необходимо заново указывать вручную при каждом использовании тестового JAR. (По крайней мере, я не нашел лучшей альтернативы.)

Если вы работаете над одним тестовым примером, не запускайте всю связку.

-Dtest=com.acme.my.pkg.Test может выделить ваш тест WIP, чтобы вы могли сэкономить много времени.

В зависимости от вашего теста, -Dtest может также поддерживать -Dtest символы .

Конечно, вы можете временно изменить массив или конфигурацию вашего тестового плагина (например, SureFire ), чтобы ограничить набор выполняемых тестов.

Отладить это

Maven-фу

Отладить тест Maven?

Если ваш тестовый исполнитель (например, SureFire) позволяет вам настроить командную строку или аргументы JVM, используемые для теста, вы можете легко настроить разветвленную JVM для ожидания отладчика, прежде чем тест начнет выполняться:

1
2
3
4
5
6
7
8
9
<build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <!-- ... -->
                    <configuration>
                        <argLine>-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,address=8000</argLine>

Отладить сам Maven ?!

Если вы пишете или устраняете проблемы с плагином или расширением Maven, было бы удобно запустить сам Maven в режиме отладки.

Maven — это, в конечном счете, Java, так что вы можете просто получить конечную команду, которая запускается при вызове, и повторно запустить ее с параметрами -Xdebug ….

Но в Maven уже есть команда кулера mvnDebug которая делает это автоматически. Он имеет тот же синтаксис, что и mvn поэтому к нему довольно легко привыкнуть.

После вызова он по умолчанию прослушивает порт 8000 для отладчика и начинает выполнение, как только он подключается; и останавливаться на точках останова, раскрывать внутренние состояния, разрешать оценку выражений и т. д.

Посмотри логи !!!

Это заслуживает отдельного раздела, потому что мы очень хорошо игнорируем вещи — прямо на наших глазах.

В самом начале

Бьюсь об заклад, есть 95% вероятность того, что Maven извергнет по крайней мере один [WARNING] в начале вашей сборки. Хотя мы почти всегда игнорируем или «откладываем» их, они в какой-то момент будут кусаться в будущем.

Прямо до конца

В случае сбоя при компиляции, тестировании или другом, Maven попытается помочь, сбросив контекст (трассировки стека, ошибки [ERROR] и т. Д.). Иногда вам нужно прокрутить страницу или две назад, чтобы найти актуальный контент, поэтому не сдавайтесь и бейте по лицу свой компьютер, с первой же попытки.

Недавно я потратил почти час, пытаясь выяснить, почему -rf : ‘d терпела неудачу; в то время как то же самое удавалось, начиная с нуля. В итоге все сводилось к двум маленьким [WARNING] строкам об systemPath разрешения зависимостей systemPath . Прямо перед моими глазами, но такой невидимый.

Maven-фу

Отчаянные времена, -X меры

В некоторых случаях, когда стандартный вывод Maven не способен точно определить проблему, лучше всего использовать Maven в режиме трассировки ( -X ). Хотя его вывод может быть пугающим, он включает в себя все, что Maven (и вы) должны знать во время сборки; версии плагинов, деревья зависимостей компиляции / тестирования, внешние вызовы команд (например, тесты); так что вы можете копать глубоко и найти виновника.

Как всегда, терпение это добродетель.

Заключительные слова

Как и во всем остальном, при использовании Maven,

  • знаю, что ты делаешь.
  • знаю, что вы действительно хотите сделать.
  • верю мавену можно это сделать , пока не доказано обратное
Смотрите оригинальную статью здесь: Несколько дополнений к вашей сумке Maven-Fu

Мнения, высказанные участниками Java Code Geeks, являются их собственными.