Maven Profiles: Declaration, Activation, -P and activeByDefault - Quiz
Total: 5 questions
1. What is a Maven profile, how do you declare one, and what can a profile override?
What is a Maven profile, how do you declare one, and what can a profile override?
A Maven profile is a named set of POM settings inside <profiles> that is applied on top of the main model only when activated: manually with -P or by a condition from <activation>. Profiles let one build behave differently without copies of pom.xml: properties for dev/test/prod environments, checks on CI, integration tests, an optional module, settings for a JDK or OS.
Declaration: each <profile> must have a unique <id>, may contain <activation> and the sections a profile is allowed to override. Profile properties are substituted in the same places as regular <properties>. In a multi-module project a profile from -P is switched on in every reactor module where a profile with that id is declared (including through the parent). The external profiles.xml existed in Maven 2; Maven 3 does not support it.
Allowed: properties; dependencies and dependencyManagement; modules (for example, shop-e2e-tests is built only by mvn verify -P e2e); in build - plugins, pluginManagement, resources, testResources, filters, finalName, defaultGoal (a profile plugin is added to the main ones, an execution with the same id is merged); repositories, pluginRepositories, distributionManagement, reporting.
Not allowed: groupId, artifactId, version, packaging, parent, and also sourceDirectory, testSourceDirectory, outputDirectory, testOutputDirectory and extensions.
A profile changes the artifact itself: a jar built with -P prod differs from one built without it.
2. What are the ways to activate a Maven profile?
What are the ways to activate a Maven profile?
Manually: -P prod, -P prod,it or <activeProfiles> in settings.xml. -P '!dev' or -P -dev switches a profile off for this run, even if its condition is met.
By default: activeByDefault works only while no other profile in the same POM is activated (with -P or by a condition), and it switches off silently. More reliable: the absence of a property (!prod) or an explicit -P dev,it.
By an <activation> condition:
- property: name
ci- set with any value (-Dci);!ci- not set; nameenvand valueci--Denv=ci; value!ci, according to the Maven documentation - the property is not set or its value is not ci; environment variables in Maven 3 - asenv.CI; - JDK:
25- the version starts with the prefix,[17,21)- from 17 inclusive up to 21 exclusive,!1.8- does not start with the prefix; - OS: family (windows, unix, mac), and also name, arch, version;
- file: exists or missing; the path may use ${basedir}, system properties and environment variables, but not <properties>.
With several conditions in one activation, since Maven 3.2.2 all must be met (before, one was enough). In Maven 3 the property condition sees system properties and -D, but not POM <properties>, so one profile cannot switch on another with its property: give them a common condition or list both (-P ci,it).
3. How do you use Maven profiles to substitute environment settings into resources, and how do Maven profiles differ from Spring profiles?
How do you use Maven profiles to substitute environment settings into resources, and how do Maven profiles differ from Spring profiles?
Profiles and filtering: a profile sets a property (for example, db.url), and when Maven copies src/main/resources with filtering enabled (<filtering>true</filtering>), it replaces ${db.url} with the value from the active profile. With dev (activeByDefault) and prod, the line db.url=${db.url} becomes db.url=jdbc:h2:mem:shop after mvn package and db.url=jdbc:postgresql://db.example.com/shop after mvn package -P prod. With many properties, the profile adds a filter file: <filters><filter>src/main/filters/prod.properties</filter></filters> in build.
The line ${db.url} is left - the profile is not active or filtering is not enabled for the directory. The profile is active but the value is wrong - the same property is passed with -D, which takes precedence.
A Maven profile and a Spring profile are different mechanisms that share a name. A Maven profile works at build time (switched on with -P or <activation>) and changes the artifact itself: a separate jar for each environment. A Spring profile works when the application starts (application-{profile}.properties, @Profile; switched on with spring.profiles.active or SPRING_PROFILES_ACTIVE) and selects a configuration inside one artifact. For addresses, logins and log levels, Spring profiles or environment variables are usually more convenient; Maven profiles are kept for what changes the build: the set of modules, check plugins, dependencies for a specific JDK.
4. How do you check which Maven profiles are active, and how do parent POM profiles work in modules?
How do you check which Maven profiles are active, and how do parent POM profiles work in modules?
Problems with profiles are usually silent: the build passes, but with the wrong settings. So check with the maven-help-plugin goals, using the same options as the build:
mvn help:active-profiles- the active profiles of each module and the source of each one (a POM or settings.xml), an approximate line:- dev (source: com.examclouds:shop-parent:1.0-SNAPSHOT);mvn help:all-profiles- all declared profiles with an "active" flag (the format depends on the plugin version), used to check ids;mvn help:effective-pomandmvn help:effective-pom -P prod- the final models; comparing them (for example, with-Doutput=base.xmland-Doutput=prod.xml) shows what the profile adds without running the build.
A profile passed in -P but not found in any POM only gets a Maven 3.9.x warning like The requested profile "prd" could not be activated because it does not exist. - a typo in a CI script does not fail the build.
Parent profiles work in modules more subtly than ordinary inheritance: if the condition of a profile declared in the parent is met while a module is being built, the profile is applied to the parent model, and the module receives the result - properties, dependencies, plugins. The profile itself does not belong to the module; where it came from is shown by the source in help:active-profiles, and the final model by help:effective-pom in the module directory.
5. How do profiles in settings.xml and activeProfiles work, and why should passwords not be kept in pom.xml profiles?
How do profiles in settings.xml and activeProfiles work, and why should passwords not be kept in pom.xml profiles?
Profiles in settings.xml: in ~/.m2/settings.xml a profile may contain only <activation>, <properties>, <repositories> and <pluginRepositories>. They hold machine-specific settings - a corporate repository address or local paths.
activeProfiles: an id in <activeProfiles><activeProfile>company</activeProfile></activeProfiles> activates the profile with that name on every Maven run on this machine, as if it were passed in -P. Keep everything that affects the build result in pom.xml, otherwise the project builds differently for your colleagues and on CI.
Why no passwords in pom.xml profiles: pom.xml is stored in Git, and mvn deploy publishes it to the artifact repository together with all its profiles. The line <db.password>secret</db.password> in the prod profile is visible to everyone with access to Git and to everyone who downloads your POM from Nexus or Maven Central; if the secret is substituted into resources by filtering, it also ends up inside the jar. Removing it from the Git history and from published versions is much harder than never adding it.
Where secrets belong: the application gets the database password at startup (an environment variable, a secrets store), and the credentials for Maven repositories come from <servers> in settings.xml or from CI secrets.