Как заставить maven MOJO выполнять только один раз в конце сборки?
У меня есть MOJO. Я хотел бы выполнить один раз и один раз только после того, как будет проведена тестовая фаза последнего проекта в реакторе.
Использование:
if (!getProject().isExecutionRoot()) {
return ;
}
в начале метода execute() означает, что мой mojo выполняется один раз, но в самом начале сборки - перед всеми другими дочерними модулями.
Ответы
Ответ 1
Лучшее решение, которое я нашел для этого:
/**
* The projects in the reactor.
*
* @parameter expression="${reactorProjects}"
* @readonly
*/
private List reactorProjects;
public void execute() throws MojoExecutionException {
// only execute this mojo once, on the very last project in the reactor
final int size = reactorProjects.size();
MavenProject lastProject = (MavenProject) reactorProjects.get(size - 1);
if (lastProject != getProject()) {
return;
}
// do work
...
}
Это похоже на работу с небольшими иерархиями сборки, с которыми я тестировал.
Ответ 2
В блоге запись в блоге Sonatype описывается, как это сделать. Последний проект, который будет запущен, будет корневым проектом, так как он будет содержать ссылки на модули для остальных. Поэтому вам нужно пройти тест в вашем mojo, чтобы проверить, совпадает ли текущий каталог проекта с каталогом, из которого был запущен Maven:
boolean result = mavenSession.getExecutionRootDirectory().equalsIgnoreCase(basedir.toString());
В ссылочной записи есть довольно подробный пример того, как использовать это в своем mojo.
Ответ 3
Я думаю, вы можете получить то, что вам нужно, если вы используете тег @aggregator и привяжите свой mojo к одной из следующих фаз жизненного цикла:
- подготовить-пакет
- пакет
- Предварительная интеграция тест
- Интеграция-тест
- после интеграции тест
- проверить
- установить
- развертывание
Ответ 4
Решение с использованием session.getEventDispatcher() больше не работает с Maven 3.x. В этой фиксации было удалено все событие: https://github.com/apache/maven/commit/505423e666b9a8814e1c1aa5d50f4e73b8d710f4
Ответ 5
Лучшее решение полагается на расширение жизненного цикла, расширяя ваш класс от org.apache.maven.AbstractMavenLifecycleParticipant
(см. также https://maven.apache.org/examples/maven-3-lifecycle-extensions.html), который получил метод afterSessionEnd
добавлен https://issues.apache.org/jira/browse/MNG-5640 (исправлено в Maven 3.2.2).
Ответ 6
Отъезд maven-monitor API
Вы можете добавить EventMonitor к диспетчеру, а затем захватить END события "execute-execute": это отправляется после того, как все будет завершено, т.е. даже после того, как вы увидите вывод BUILD SUCCESSFUL/FAILED.
Вот как я недавно использовал его, чтобы напечатать резюме в конце:
/**
* The Maven Project Object
*
* @parameter expression="${project}"
* @required
* @readonly
*/
protected MavenProject project;
/**
* The Maven Session.
*
* @parameter expression="${session}"
* @required
* @readonly
*/
protected MavenSession session;
...
@Override
public void execute() throws MojoExecutionException, MojoFailureException
{
//Register the event handler right at the start only
if (project.isExecutionRoot())
registerEventMonitor();
...
}
/**
* Register an {@link EventMonitor} with Maven so that we can respond to certain lifecycle events
*/
protected void registerEventMonitor()
{
session.getEventDispatcher().addEventMonitor(
new EventMonitor() {
@Override
public void endEvent(String eventName, String target, long arg2) {
if (eventName.equals("reactor-execute"))
printSummary();
}
@Override
public void startEvent(String eventName, String target, long arg2) {}
@Override
public void errorEvent(String eventName, String target, long arg2, Throwable arg3) {}
}
);
}
/**
* Print summary at end
*/
protected void printSummary()
{
...
}
Ответ 7
Обычно это вопрос конфигурации. Возможно, вам придется настроить проект только для mojo и сделать его зависимым от всех других проектов. Или вы можете заставить один из дочерних проектов быть последним, сделав его зависимым от всех других детей.