你怎么强迫maven MOJO在构建结束时只执行一次?

我有一个MOJO我想执行一次,并且只有在反应堆的最后一个项目的测试阶段之后运行。

使用:

if (!getProject().isExecutionRoot()) { return ; } 

在execute()方法的开头,意味着我的mojo被执行一次,但是在构建的最开始 – 在所有其他子模块之前。

我发现的最佳解决方案是:

 /** * 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 ... } 

这似乎适用于我测试过的小型构建层次结构。

最好的解决方案是通过从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中修复)。

有一个Sonatype博客条目描述了如何执行此操作。 要运行的最后一个项目将是根项目,因为它将包含对其余项目的模块引用。 因此,您需要在mojo中进行测试,以检查当前项目的目录是否与启动Maven的目录相同:

 boolean result = mavenSession.getExecutionRootDirectory().equalsIgnoreCase(basedir.toString()); 

在引用的条目中有一个非常全面的例子,说明如何在你的mojo中使用它。

如果您使用@aggregator标记并将mojo绑定到以下生命周期阶段之一,我想您可能会得到所需内容:

  • 制备包
  • 预集成测试
  • 集成测试
  • 整合后的测试
  • 校验
  • 安装
  • 部署

使用session.getEventDispatcher()的解决方案自Maven 3.x起不再有效。 整个事件已在此提交中删除: https : //github.com/apache/maven/commit/505423e666b9a8814e1c1aa5d50f4e73b8d710f4

查看maven-monitor API

您可以将EventMonitor添加到调度程序,然后捕获’reactor-execute’事件的END:在完成所有操作后调度,即使在您看到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() { ... } 

通常,这是配置问题。 您可能必须为mojo设置项目并使其依赖于所有其他项目。 或者您可以通过使其依赖于所有其他子项来强制其中一个子项目成为最后一个。