In projects with many parent POMs, profiles, and plugin management sections, one can easily end up in a situation where the effective configuration for a plugin is the result of merging many configuration blocks from the various POM sources together.
Not knowing the details of this merge process naturally leads to some confusion about why an effective configuration looks the way it looks, or why changes to some parent POM’s configuration don’t have the desired effects in child POMs.
This post attempts to shed some light on this confusion, and provides you with a sense of how Maven merges plugin configuration from multiple sources. This post uses attributes which are available in Maven 3.0.2.
The Simplest Case: Merging Parent and Child POMs
As a concrete example, let’s assume we have a parent POM with the following plugin configuration:
Let’s further assume we have a child POM that inherits from the above parent and that specifies the following configuration for the same plugin:
Now, as an invocation of mvn help:effective-pom will show you, the effective plugin configuration for the child project will be:
This result demonstrates the default merge behavior. The configuration elements are recursively merged based on the element name, and elements from the parent POM are only added to the result when the child POM does not contain an equally named element. Let me stress that merging of plugin configuration is purely an operation on the XML DOM tree. In particular, the merge process has no knowledge of the actual data structures in the plugin that will be configured nor their semantics. In other words, configuration values are generally not considered as merge keys when combining child and parent elements, only the name of the configuration elements is used to identify conflicting elements that need to be merged.
Controlling the Merge Process with combine.children and combine.self
Sometimes the default merge behavior doesn’t produce the intended configuration. In this case, one can use two attributes on the child configuration to adjust the behavior as shown in the next child POM:
Assuming the above child POM still inherits from the previously sketched parent POM, one would now get the following effective configuration:
As you can see here, usage of combine.children="append" results in the concatenation of parent and child elements, in that order. The attribute combine.self="override" on the other hand completely suppresses parent configuration to be inherited. That said, it’s senseless to specify both combine.self="override" and combine.children="append" for a configuration element, the former directive takes precedence.
Note that these attributes only apply to the configuration element they are declared on, and are not propagated to nested elements. That is if the <item> element from our last child POM would be a complex structure instead of a mere string, its sub elements would still be subject to the default merge strategy.
The combine.* attributes are however inherited along a hierarchy of POMs. So some care must be taken when adding those attributes to a configuration snippet in a parent POM as this might affect child or grand-child POMs unless those explicitly override the attributes themselves.
Last but not least, please note that the attributes described here to control merging only apply to plugin configuration. You cannot use these attributes on other elements of the POM.