76

In a multi-module project, how can you specify that you want to execute a plugin goal in all the child-modules, but not on the parent project? There is <pluginManagement>, but that only defines the configuration for the execution -- the child modules would still need to reference the plugin to get the goal executed:

[...] However, this only configures plugins that are actually referenced within the plugins element in the children. (POM Reference)

Any other way to achieve this?

UPDATE: I've tried this according to Pascal's advice:

<!-- ... -->
<packaging>pom</packaging>
<modules>
  <module>child</module>
</modules>

<build>
  <plugins>
    <plugin>
      <artifactId>maven-jar-plugin</artifactId>
      <executions>
        <execution>
        <phase>integration-test</phase>
        <goals>
          <goal>jar</goal>
        </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>
<!-- ... -->

This will still generate a .jar for the parent project, even though the jar goal is bound to the integration-test phase.

mkobit
  • 43,979
  • 12
  • 156
  • 150
Lóránt Pintér
  • 10,152
  • 14
  • 47
  • 53
  • 1
    can't you just bind it to a phase which is not executed in a pom-type project (which your parent should be?) – falstro Oct 26 '09 at 15:34
  • @roe I think your comment could be turned to an answer :-) I would like to know, and I would vote for it ;-) – KLE Oct 26 '09 at 15:50
  • @KLE It was not an answer, I was trying to help the brainstorm. I have no idea how to actually do this. – falstro Oct 26 '09 at 15:58
  • I think, in general, you'd like to have the goal realize it's not applicable to the parent project, and just specify it in parent project. The second option I can think of, which probably suits your needs even worse, is to define a new packaging form, since you need to specify a packaging anyway... – falstro Oct 26 '09 at 16:01
  • We need some help from Rich Seller ! Rich, are you there? ;-) http://stackoverflow.com/users/123582/rich-seller – KLE Oct 26 '09 at 16:10
  • Maybe you guys could vote for the question, to make it more attractive to answerers? – KLE Oct 26 '09 at 16:13

7 Answers7

40

According to the Default Lifecycle Bindings, the bindings for a packaging pom are:

Default Lifecycle Bindings - Packaging pom

package       site:attach-descriptor  
install       install:install  
deploy        deploy:deploy

So if your parent POM has a <packaging>pom<packaging> (this should be the case as pointed out in a comment) and if you bind your plugins to other phases than those above (see the Lifecycle Reference for a comprehensive list), they won't be executed during the build of the parent POM.

(EDIT: My initial answer is just wrong. If you bind a plugin goal to a particular phase, it will be triggered during that phase, regardless of the packaging of the project. The Default Lifecycle Bindings don't have anything to do with that, they are just default lifecycle bindings. All what matters is if the phase to which the plugin is bound is part of the build lifecyle.)

As you pointed out, you can use the pluginManagement in the parent pom for the configuration of the plugin but if you really want to execute a plugin goal in children modules and not in the parent (you might have good reasons to do this but most of time, plugins won't have much effet on a module with a pom packaging that doesn't have any content), you'll have to reference plugins in the plugins element in the children.

Applied to your example, the parent pom.xml could define the following specifications:

<project>
  <packaging>pom</packaging>
  ...
  <modules>
    <module>child</module>
  </modules>
  ...
  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-jar-plugin</artifactId>
          <version>2.2</version>
          <executions>
            <execution>
              <id>my-execution-id</id>
              <phase>integration-test</phase>
              <goals>
                <goal>jar</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
        ...
      </plugins>
    </pluginManagement>
  </build>
  ...
</project>

And in every child pom.xml, only the following is required:

<project>
  ...
  <build>
    ...
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
      </plugin>
    </plugins>
    ...
  </build>
</project>
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • 1
    Pascal answer is correct. In parent POM ``section defines conifugration for plugins but not forces theirs executions, you need to place also `` section to spread excutions of these plugins into child modules. – cetnar Oct 26 '09 at 19:27
  • 1
    I've tried this with the `maven-jar-plugin`, but it still creates a .jar for my parent POM project. I'll add details to the question. – Lóránt Pintér Oct 27 '09 at 08:31
28

The described solution with plugin management is certainly correct, but in certain cases it does not fit. Suppose you would like to run several jar:jar goals in the child module each configured with its own settings (configuration) per execution. Or in general, when you don't want to force child poms to explicitly trigger the plugin(s).

In this case the solution that worked for me was to define the executions in the parent pom under a specific profile, and have it activated only in child poms for example by checking for existence of some file or property:

<profile>
    <id>generate-dc</id>
    <activation>
        <file>
            <exists>src/main/assembly/some.xml</exists>
        </file>
    </activation>

Then plugins won't be executed in the parent, but will be executed in all children if those contain the file, or set some property.

Gwenc37
  • 2,064
  • 7
  • 18
  • 22
Mikhail
  • 281
  • 3
  • 3
  • This is certainly not pretty, but it's the only work around I've found to do this. I would suggest, however, to use an environment property like ${project.name} or ${pom.name} to trigger the activation instead of the file, but it's a case by case thing, of course. – Miquel Apr 20 '12 at 17:04
  • Ha, this suggestion led me to the only solution for proper "composed" mix-in Maven segments. Make empty profile selector files. It's awful but it could be worse. – Reinderien May 27 '15 at 03:54
  • 1
    Great solution for conditionally executing plugins, saved my day! – Christoffer Soop Oct 08 '15 at 14:11
  • Very useful to avoid repeating code, especially in case of many plugins. Unfortunately, activation by a property does not work because Maven supports system properties as properties. – mm759 Dec 28 '17 at 11:51
11

I had a similar requirement to run some plugins in the child but not the parent POM. i achieved this by stating <skip>true</skip> in the parent POM.

The parent pom entry is below:

<plugin>
    <groupId>eviware</groupId>
    <artifactId>maven-soapui-plugin</artifactId>
    <version>4.0.0</version>
    <inherited>false</inherited>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.2</version>
        </dependency>
    </dependencies> 
    <configuration>
        <skip>true</skip>
    </configuration>
</plugin> 

The child project pom entry is below

<plugins>
    <plugin>
        <groupId>eviware</groupId>
        <artifactId>maven-soapui-plugin</artifactId>
        <version>4.0.0</version>
        <configuration>
            <settingsFile>site-service-web/src/test/soapui/soapui-settings.xml</settingsFile>
            <projectFile>site-service-web/src/test/soapui/PodifiSite-soapui-project.xml</projectFile>
            <outputFolder>site-service-web/target/surefire-reports</outputFolder>
            <junitReport>true</junitReport>
            <exportwAll>true</exportwAll>
            <printReport>true</printReport>
        </configuration>
    </plugin>
</plugins>
mkobit
  • 43,979
  • 12
  • 156
  • 150
Rafeeq
  • 259
  • 3
  • 3
  • Warning the above setting might work but in complex cases where other pom(s) inherit the parent and specifically the plugin that was defined as skip true, you will have a problem since the plugin WILL not execute, unless you define it or configure it. For rarely used plugins you want any problems but for plugins like maven-resources-plugin the default skip true might be a problem – javapapo Jul 23 '14 at 14:29
  • This worked for me. Although the plugin I needed to use - appassembler - doesn't really skip I just put some placeholder configuration in the top level POM and my child modules started to run the appassembler goal correctly. Thanks! :) – Greg Dubicki Feb 25 '15 at 10:48
1

This below config worked for me. Add the plugin in both the parent and child pom.

Parent :

<build>
  <plugins>
    <plugin>
      <artifactId>maven-jar-plugin</artifactId>
      <inherited>true</inherited>
      <executions>
        <execution>
        <phase>integration-test</phase>
        <goals>
          <goal>jar</goal>
        </goals>
        </execution>
      </executions>
      <configuration>
         <skip>true</skip>
      </configuration>
    </plugin>
  </plugins>
</build>

Child

<build>
  <plugins>
    <plugin>
      <artifactId>maven-jar-plugin</artifactId>
      <inherited>false</inherited>
      <executions>
        <execution>
        <phase>integration-test</phase>
        <goals>
          <goal>jar</goal>
        </goals>
        </execution>
      </executions>
      <configuration>
         <skip>false</skip>
      </configuration>
    </plugin>
  </plugins>
</build>
lakshmanas
  • 119
  • 1
  • 1
0

I tried the answer from Pascal but it did not work for me. The plugins referenced in the child pom did not execute, I'm assuming because they did not have a build phase binding.

The post here describes a solution that works by binding the plugins to execution ids and build phases: How to override default binding to phase of a Maven plugin

I'd recommend that to anyone else trying to get this working.

Community
  • 1
  • 1
0

Create a skipme property in both parent and child. Set it to true in the parent. Set it to false in child. You don't have to add the plugin again in child, it will be inherited This way you can turn a plugin execution on/off anywhere easily in module hierarchy (child/grandchild/greatgrandchild) Also suggest using execution IDs, but not mandatory.

Parent:

  <properties>
  <skipme>true<skipme>
  </properties>
        <build>
              <plugins>
                    <plugin>
                          <artifactId>maven-jar-plugin</artifactId>                             
                          <executions>
                                <execution>                                          
                                      <goals>
                                            <goal>jar</goal>
                                      </goals>
                                </execution>
                          </executions>
                          <configuration>
                                <skip>${skipme}</skip>
                          </configuration>
                    </plugin>
              </plugins>
        </build>

Child:

  <properties>
              <skipme>false<skipme>
  </properties>
  
  

Another trick is to use phase. Create a "myphase" property in both parent and child. Set it to "none" in the parent. Set it to "integration-test" (or as desired) in child. You don't have to add the plugin again in child, it will be inherited

Parent:

  <properties>
    <myphase>none<myphase>
  </properties>
        <build>
              <plugins>
                    <plugin>
                          <artifactId>maven-jar-plugin</artifactId>                            
                          <executions>
                                <execution>
                                      <phase>${myphase}</phase>
                                      <goals>
                                            <goal>jar</goal>
                                      </goals>
                                </execution>
                          </executions>
                    </plugin>
              </plugins>
        </build>

Child:

  <properties>
              <myphase>integration-test<myphase>
  </properties>
Mike y
  • 1
  • 1
-2

Use <inherited>false</inherited> under the plugins section in the parent project.

Plese refer to this page for more information.

Richard Erickson
  • 2,568
  • 8
  • 26
  • 39
Y L
  • 21
  • 2
  • Take care with this approach when using aggregating modules. Maven tries executing goals on all aggregated modules, so, for example, `jar:jar` will fail beyond the first module. – Dragas Oct 10 '18 at 07:55
  • 1
    This is doing the opposite to what OP says.. its executing the module on parent but not child (or I am missing something) – Whimusical Feb 05 '20 at 14:57