CI servers, private repositories and environment-specific builds all rely on profiles and settings.
Properties are placeholders used throughout the POM: ${project.version}, ${project.basedir}, environment variables ${env.HOME}, system properties, and your own from <properties>. Override them from the command line with -Dname=value.
Profiles are blocks of POM configuration applied conditionally. A profile can add dependencies, plugins, properties and modules. Activate one:
- Explicitly:
mvn package -Pprod(or-P!prodto deactivate). - By property:
<activation><property><name>env</name><value>ci</value></property></activation>matches-Denv=ci. - By JDK, OS, or a file's existence; or
<activeByDefault>true</activeByDefault>, which is switched off as soon as any other profile is active (a common surprise).
mvn help:active-profiles lists what is active. Don't use profiles to produce different artifacts from the same version (a "prod jar" and a "dev jar" with the same coordinates); keep environment config outside the artifact.
settings.xml (~/.m2/settings.xml, or $MAVEN_HOME/conf globally) is personal and machine-specific, never committed:
<mirrors>redirect all repository traffic to a company proxy such as Nexus or Artifactory.<servers>hold credentials for deploying or for private repositories, matched by<id>; encrypt passwords withmvn --encrypt-password.<profiles>and<activeProfiles>for local defaults;<proxies>for HTTP proxies.
CI typically supplies a settings file with mvn -s ci-settings.xml and credentials from environment variables (${env.NEXUS_TOKEN}).
Example
<!-- pom.xml -->
<profiles>
<profile>
<id>ci</id>
<activation>
<property><name>env</name><value>ci</value></property> <!-- mvn -Denv=ci -->
</activation>
<properties>
<skipITs>false</skipITs>
</properties>
</profile>
<profile>
<id>jdk-preview</id>
<activation><jdk>[25,)</jdk></activation>
<properties><maven.compiler.enablePreview>true</maven.compiler.enablePreview></properties>
</profile>
</profiles>
<!-- ~/.m2/settings.xml (not committed) -->
<settings>
<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>https://nexus.acme.com/repository/maven-public/</url>
</mirror>
</mirrors>
<servers>
<server><id>nexus</id><username>ci</username><password>${env.NEXUS_TOKEN}</password></server>
</servers>
</settings>
<!-- mvn verify -Pci mvn help:active-profiles -->Remember
- Properties parameterize the POM; override with -Dname=value
- Profiles add configuration conditionally (-P, properties, JDK, OS)
- activeByDefault switches off when another profile is active
- settings.xml holds mirrors and credentials and stays uncommitted
Watch out for
- Baking environment-specific values into the artifact through profiles, producing jars that differ by build machine.