Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven2 - problem with pluginManagement and parent-child relationship

Tags:

maven-2

from maven documentation

pluginManagement: is an element that is seen along side plugins. Plugin Management contains plugin elements in much the same way, except that rather than configuring plugin information for this particular project build, it is intended to configure project builds that inherit from this one. However, this only configures plugins that are actually referenced within the plugins element in the children. The children have every right to override pluginManagement definitions.

Now : if I have this in my parent POM

  <build>
   <pluginManagement>
      <plugins>
        <plugin>
          <artifactId>maven-dependency-plugin</artifactId>
          <version>2.0</version>
          <executions>
             Some stuff for the children
            </execution>
          </executions>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

and I run mvn help:effective-pom on the parent project I get what I want, namely the plugins part directly under build (the one doing the work) remains empty.

Now if I do the following :

  <build>
   <pluginManagement>
      <plugins>
        <plugin>
          <artifactId>maven-dependency-plugin</artifactId>
          <version>2.0</version>
          <executions>
             Some stuff for the children
            </execution>
          </executions>
        </plugin>
      </plugins>
    </pluginManagement>
<plugins>
  <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.0.2</version>
    <inherited>true</inherited>
    <configuration>
      <source>1.6</source>
      <target>1.6</target>
    </configuration>
  </plugin>
</plugins>
  </build>

mvn help:effective-pom I get again just what I want, the plugins contains just what is declared and the pluginManagement section is ignored.

BUT changing with the following

  <build>
   <pluginManagement>
      <plugins>
        <plugin>
          <artifactId>maven-dependency-plugin</artifactId>
          <version>2.0</version>
          <executions>
             Some stuff for the children
            </execution>
          </executions>
        </plugin>
      </plugins>
    </pluginManagement>
    <plugins>
      <plugin>
        <artifactId>maven-dependency-plugin</artifactId>
          <version>2.0</version>
          <inherited>false</inherited> <!-- this perticular config is NOT for kids... for parent only -->
            <executions>
             some stuff for adults only
            </execution>
          </executions>
       </plugin>
    </plugins>
  </build>

and running mvn help:effective-pom the stuff from pluginManagement section is added on top of what is declared already. as such :

  <build>
   <pluginManagement>
     ...
   </pluginManagement>
    <plugins>
      <plugin>
        <artifactId>maven-dependency-plugin</artifactId>
          <version>2.0</version>
          <inherited>false</inherited> <!-- this perticular config is NOT for kids... for parent only -->
              <executions>
                 Some stuff for the children
                </execution>
            <executions>
             some stuff for adults only
            </execution>
          </executions>
       </plugin>
    </plugins>
  </build>

Is there a way to exclude the part for children from the parent pom's section ? In effect what I want is for the pluginManagement to behave exactly as the documentation states, that is I want it to apply for children only but not for the project in which it is declared.

As a corrolary, is there a way I can override the parts from the pluginManagement by declaring the plugin in the normal build section of a project ? whatever I try I get that the section is added to executions but I cannot override one that exists already.

EDIT:

I never did find an acceptable solution for this and as such the issue remains open. Closest solution was offered below and is currently the accepted solution for this question until something better comes up. Right now there are three ways to achieve the desired result (modulate plugin behaviour depending on where in the inheritance hierarchy the current POM is):

1 - using profiles, it will work but you must beware that profiles are not inherited, which is somewhat counter intuitive. They are (if activated) applied to the POM where declared and then this generated POM is propagated down. As such the only way to activate the profile for child POM is specifically on the command line (least I did not find another way). Property, file and other means of activation fail to activate the POM because the trigger is not in the POM where the profile is declared.

2 - (this is what I ended up doing) Declare the plugin as not inherited in the parent and re-declare (copy-paste) the tidbit in every child where it is wanted. Not ideal but it is simple and it works.

3 - Split the aggregation nature and parent nature of the parent POM. Then since the part that only applies to the parent is in a different project it is now possible to use pluginManagement as firstly intended. However this means that a new artificial project must be created that does not contribute to the end product but only serves the could system. This is clear case of conceptual bleed. Also this only applies to my specific and is hard to generalize, so I abandoned efforts to try and make this work in favor of the not-pretty but more contained cut and paste patch described in 2.

If anyone coming across this question has a better solution either because of my lack of knowledge of Maven or because the tool evolved to allow this please post the solution here for future reference.

Thank you all for your help :-)

like image 890
Newtopian Avatar asked Aug 12 '09 13:08

Newtopian


People also ask

What is the purpose of the pluginManagement block?

pluginManagement: is an element that is seen along side plugins. Plugin Management contains plugin elements in much the same way, except that rather than configuring plugin information for this particular project build, it is intended to configure project builds that inherit from this one.

Can a POM file have multiple parents?

You can achieve multiple inheritance with profiles: You create (multiple) profiles in the root pom, and auto activate any variation of these profiles achieves multiple inheritance of maven configuration. This is not ideal because child projects cannot control the activation of profiles defined in the parent POM.

Are plugins inherited from parent pom?

Maven allows us to build a project using the concept of inheritance. When a parent POM defines a plugin, all of the child modules inherit it.

What is pluginManagement?

In multi-module projects, pluginManagement allows you to configure plugin information that can be used as required by child projects. The parent pom can define the configurations for various plugins used by different child projects. Each child project can chose the plugins that it needs for the build.


2 Answers

Adding the plugin configuration to pluginManagement means that this configuration will be used if the plugin is declared, but you still need to declare the plugin in the build section of any POM that wants to use it.

The key part that explains this from the section you quoted is:

However, this only configures plugins that are actually referenced within the plugins element in the children

So if you do this in the child pom the configuration from the parent will be applied:

<build>
  <plugins>
    <plugin>
      <artifactId>maven-dependency-plugin</artifactId>
    </plugin>
  </plugins>
</build>

Update: To answer the actual question, the content from the pluginManagement section is always merged with any plugin declaration. To avoid the parent doing this, you can define the pluginManagement section within a profile, and activate that profile on child projects but not the parent. The child projects would then have to declare that profile.

For example:

<profiles>
  <profile>
    <id>for-children</id>
    <build>
      <pluginManagement>
        <plugins>
          <plugin>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.0</version>
            <executions>
              <!--Some stuff for the children-->
            </executions>
          </plugin>
        </plugins>
      </pluginManagement>
    </build>  
  </profile>
</profiles>
<build>
  <plugins>
    <plugin>
      <artifactId>maven-dependency-plugin</artifactId>
        <version>2.0</version>
        <inherited>false</inherited> <!-- this perticular config is NOT for kids... for parent only -->
          <!--some stuff for adults only-->
        </executions>
     </plugin>
  </plugins>
</build>
like image 152
Rich Seller Avatar answered Sep 17 '22 12:09

Rich Seller


I always used to think that a child POM can inherit a plugin definition from its parent's pluginManagement section and specify only the executions it wants to run from that plugin by referencing them by ID and binding the execution to a phase. As long as the parent definition is in pluginManagement (and not directly in plugins) and is not bound to a phase, only the specific execution (with ID) will be run in that phase.

From reading the above, and from my own current problem, it looks like that's not true: it looks like a child POM will inherit the entire configuration of the plugin, including all executions. In terms of executions, the only thing the child can do is to override specific values - it cannot pick which executions to run, and which not to.

Is this a bug? What's the use of being able to bind each execution to a phase (or not), if all executions will be run? I've only seen it with maven-dependency-plugin:unpack (bound to package phase), but with other plugins I might just have been lucky...

Damn.

like image 23
Cornel Masson Avatar answered Sep 19 '22 12:09

Cornel Masson