You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

POM Expression evaluation

Expressions in the pom generally look like this:

 ${foo}

or

 ${bar.baz}

The bar in the last example can be a special token: pom, env, or the legacy project which is deprecated
and means the same as pom.
In this case bar is called a prefix and the baz expression is evaluated against the project model
using reflection, so

 ${pom.version}

evalueates to the value of the <project><version> tag.

If the prefix is env, the expression evaluates to the value of System.getEnv( "baz" );

In all other cases, if the prefix is NOT pom or env, the current context is consulted.
It typically contains the basedir value, the system properties, and any key/value pairs specified with the -Dkey=value commandline option.

When the context does not contain the value for the expression, the POM properties are consulted.

Maven 2.0.x behaviour

In Maven 2.0.x the prefix was discarded if it was pom, project, or env. The remaining expression was evaluated using the following algorithm:

  • check the context; if the key/value exists, use that. If the key exists but the value is null, skip this term, and leave the _${expression} as is.
  • check the model properties. If that value exists, use that.
  • check the model using reflection. If that yields a value, use that.
  • check the environment variables
  • if the expression refers to itself abort. This check is broken in several ways:
    • it tests for string equality but both pom.* and project.* refer to the same object. so "$
      Unknown macro: {pom.foo}
      " evaluating to "$
      Unknown macro: {project.foo}
      " will introduce recursion:
    • since it discards the prefix,
      <scm><connection>${scm.connection}</connection></scm>
      will introduce recursion.
    • it only checks 1 level deep:
      <properties><foo>${bar}</foo><bar>${foo}</foo></properties>
      . Even if this works, try adding another level,
      or even this:
      <properties><foo>${pom.bar}</foo><bar>${foo}</bar></properties>
      .

Some unexpected results can occur, and have caused some bugs. Poms containing _${pom.version} or even _${version}
can break the build if -Dversion=foo is supplied on the commandline.

So, expressions like ${version} or ${artifactId}, or even $_{pom.version} can cause all sorts of problems.

Final algorithm.

The algoritm is simple, were it not for backwards compatibility check due to the enormous amount of faulty poms in the repository.
Therefore, we'll use the new approach but still support legacy (broken) poms, though the behaviour may be a little bit different.

The first problem we need to solve is the fact that both ${pom.version} and _${version} are resolved using the same algorithm.
This will solve the problem of commandline arguments and system properties inadvertedly overriding pom attributes, like _${version}.

  • No labels