Maven Model Builder

The effective model builder, with profile activation, inheritance, interpolation, ...

The main component is ModelBuilder (javadoc, source), with its DefaultModelBuilder implementation (javadoc, source) that manages the steps sequence.

The sequence is divided into 2 phases:

  • phase 1
    • profile activation: see available activators. Notice that model interpolation hasn't happened yet, then interpolation for file-based activation is limited to ${basedir} (since Maven 3), ${rootDirectory} (since Maven 4), system properties and user properties
    • file model validation: ModelValidator (javadoc), with its DefaultModelValidator implementation (source)
  • phase 2, with optional plugin processing
    • Build up a raw model by re-reading the file and enriching it based on information available in the reactor. Some features:
      • Resolve version of versionless parents based on relativePath (including ci-friendly versions)
      • Resolve version of versionless dependencies that are part of the reactor
    • raw model validation: ModelValidator (javadoc), with its DefaultModelValidator implementation (source)
    • model normalization - merge duplicates: ModelNormalizer (javadoc), with its DefaultModelNormalizer implementation (source)
    • profile injection: ProfileInjector (javadoc), with its DefaultProfileInjector implementation (source)
    • parent resolution until super-pom
    • inheritance assembly (see below)
    • model interpolation (see below)
    • url normalization: UrlNormalizer (javadoc), with its DefaultUrlNormalizer implementation (source)
    • model path translation: ModelPathTranslator (javadoc), with its DefaultModelPathTranslator implementation (source)
    • plugin management injection: PluginManagementInjector (javadoc), with its DefaultPluginManagementInjector implementation (source)
    • (optional) lifecycle bindings injection: LifecycleBindingsInjector (javadoc), with its DefaultLifecycleBindingsInjector implementation in maven-core (source)
    • dependency management import (for dependencies of type pom and scope import in the <dependencyManagement> section)
    • dependency management injection: DependencyManagementInjector (javadoc), with its DefaultDependencyManagementInjector implementation (source)
    • model normalization - inject default values: ModelNormalizer (javadoc), with its DefaultModelNormalizer implementation (source)
    • (optional) reports configuration: ReportConfigurationExpander (javadoc), with its DefaultReportConfigurationExpander implementation (source)
    • (optional) reports conversion to decoupled site plugin: ReportingConverter (javadoc), with its DefaultReportingConverter implementation (source)
    • (optional) plugins configuration: PluginConfigurationExpander (javadoc), with its DefaultPluginConfigurationExpander implementation (source)
    • effective model validation: ModelValidator (javadoc), with its DefaultModelValidator implementation (source)

Inheritance Assembly

Inheritance Assembly consists in filling current model empty fields with values taken from parent model. It is done in InheritanceAssembler (javadoc), with its DefaultInheritanceAssembler implementation (source).

By default, every model field is inherited as-is from parent, with a few exceptions that are intentionally not inherited: modelVersion, artifactId, profiles (injected in phase 1) and prerequisites.

Notice that the 5 URLs from the model (project.url, project.scm.connection, project.scm.developerConnection, project.scm.url and project.distributionManagement.site.url) have a special inheritance handling:

  • if not configured in current model, the inherited value is the parent's one with current artifact id appended,
  • since Maven 3.5.0, if project.directory POM property value is defined, it is used instead of artifact id: this permits default inheritance calculations when module directory name is not equal to artifact id. Notice that this property is not inherited from a POM to its child: child's POM will use child artifact id if property is not set.
  • since Maven 3.6.1, inheritance can avoid appending any path to parent value by setting model attribute value to false for each url: project/@child.project.url.inherit.append.path, project/distributionManagement/site/@child.site.url.inherit.append.path, project/scm/@child.scm.connection.inherit.append.path, project/scm/@child.scm.developerConnection.inherit.append.path and project/scm/@child.scm.url.inherit.append.path.

Model Interpolation

Model Interpolation consists in replacing ${...} with calculated value. It is done in StringVisitorModelInterpolator (javadoc, source).

Notice that model interpolation happens after profile activation, and that profile activation doesn't benefit from every values: interpolation for file-based activation is limited to ${basedir} (which was introduced in Maven 3 and is not deprecated in this context) and ${rootDirectory} (introduced in Maven 4), system properties and user properties.

Values are evaluated in sequence from different syntaxes:

value evaluation result common examples
project.* 
pom.* (deprecated
* (deprecated)
POM content (see POM reference) ${project.version} 
${project.build.finalName} 
${project.artifactId} 
${project.build.directory}
project.basedir 
pom.basedir (deprecated
basedir (deprecated)
the directory containing the pom.xml file ${project.basedir}
project.baseUri 
pom.baseUri (deprecated)
the directory containing the pom.xml file as URI ${project.baseUri}
project.rootDirectory the project's root directory (containing a .mvn directory or with the root="true" xml attribute) ${project.rootDirectory}
build.timestamp 
maven.build.timestamp
the UTC timestamp of build start, in yyyy-MM-dd'T'HH:mm:ss'Z' default format, which can be overridden with maven.build.timestamp.format POM property ${maven.build.timestamp}
* user properties, set from CLI with -Dproperty=value ${skipTests}
* model properties, such as project properties set in the pom ${any.key}
maven.home The path to the current Maven home. ${maven.home}
maven.version The version number of the current Maven execution (since 3.0.4). For example, "3.0.5". ${maven.version}
maven.build.version The full build version of the current Maven execution (since 3.0.4). For example, "Apache Maven 3.2.2 (r01de14724cdef164cd33c7c8c2fe155faf9602da; 2013-02-19T14:51:28+01:00)". ${maven.build.version}
maven.repo.local The repository on the local machine Maven shall use to store installed and downloaded artifacts (POMs, JARs, etc). ${user.home}/.m2/repository
* Java system properties (see JDK reference) ${user.home} 
${java.home}
* User properties ${foo}
env.* 
*
environment variables ${env.PATH}
settings.* Local user settings (see settings reference) ${settings.localRepository}
changelist  
revision  
sha1
CI friendly placeholders for the project version (see Maven CI Friendly Versions) 1.0.0-${changelist}-SNAPSHOT

Notice

  • after model interpolation, ${...} content can remain in the model that will be evaluated later when setting plugin parameters. This happens in particular with settings.* values for Settings Model,
  • encoding configuration have been defined as POM properties looking like POM content but not added to POM model to maintain compatibility with previous Maven versions:
    • ${project.build.sourceEncoding} for source files encoding (defaults to UTF-8 since Maven 4.0.0, no default value was provided in Maven 3.x, meaning that the platform encoding was used by plugins)
    • ${project.reporting.outputEncoding} for reporting output files encoding (defaults to UTF-8 since Maven 4.0.0, no default value was provided in Maven 3.x, plugins usually defaulting to UTF-8)