Using (and not misusing) Maven profiles for environments, writing a custom plugin, generating documentation, an unavailable dependency, reducing project and artifact size, settings.xml, diagnosing slowing builds, enforcing standards and static analysis, dependency:tree, and handling an incompatible dependency version.
Published September 25, 2026
These questions separate "I've used Maven" from "I maintain the build". Watch the traps: environment-specific artifacts, FindBugs (long dead), and installing JARs by hand on laptops. The modern answers are build once, SpotBugs, and a repository manager.
Short answer: A profile changes the build: extra dependencies, plugin configuration, properties or modules. It's activated with -Pname, or automatically by JDK version, OS, a property or a missing file. Legitimate uses:
-Pnative, -Pintegration-tests, -Pcoverage);Common trap: building different artifacts per environment (-Pprod baking the production database URL into the JAR). That breaks "build once, deploy everywhere", because what you tested isn't what you deploy. Keep the artifact environment-neutral, and inject environment configuration at runtime (Spring profiles, environment variables, a config server).
<profiles>
<profile>
<id>integration-tests</id>
<build><plugins><plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions><execution><goals><goal>integration-test</goal><goal>verify</goal></goals></execution></executions>
</plugin></plugins></build>
</profile>
</profiles>
Short answer (a model story): "We needed every service JAR to include a release-manifest.json with the git commit, dependency licences and API version, which no existing plugin produced in our format. I wrote a plugin: a Mojo class annotated with @Mojo(name = "manifest", defaultPhase = LifecyclePhase.PREPARE_PACKAGE), with @Parameter fields injected from the POM and the MavenProject for the dependency data. It's built with maven-plugin-plugin. The challenges were reproducibility (stable ordering, no timestamps, so builds stay byte-identical) and testing (the Maven plugin testing harness plus an integration test project). We published it to Nexus, and bound it in the parent POM."
Key points to cover:
exec-maven-plugin, maven-antrun-plugin, build-helper, git-commit-id-maven-plugin. A custom plugin is justified when the logic is reused across many projects.Short answer:
mvn site, with maven-site-plugin) produces a website from reporting plugins: Javadoc, Surefire and Failsafe reports, JaCoCo coverage, dependency and licence reports, SpotBugs, Checkstyle.maven-javadoc-plugin (a -javadoc.jar for published libraries), OpenAPI specs from springdoc (springdoc-openapi-maven-plugin), or generated from the spec.Key points to cover:
Short answer:
-e/-X, check settings.xml mirrors, and check whether the version really exists.LATEST/RELEASE), and avoid depending on obscure third-party repositories.Common trap: mvn install:install-file on your laptop "fixes" your build, but not CI or your teammates' builds, and it hides the real problem. Use it only for a one-off local experiment.
Short answer:
mvn dependency:analyze reports "declared but unused" and "used but undeclared".provided, test and runtime keep things out of the packaged artifact.maven-shade-plugin with minimizeJar only for libraries that must be self-contained.settings.xml for?Short answer: It configures Maven itself, on a given machine or user, rather than a project. User settings live in ~/.m2/settings.xml, and global ones in ${maven.home}/conf/settings.xml. It holds:
<servers>, referenced by the ID of the repository or distribution entries);<settings>
<mirrors>
<mirror><id>company</id><mirrorOf>*</mirrorOf><url>https://nexus.acme.internal/repository/maven-all/</url></mirror>
</mirrors>
<servers>
<server><id>company</id><username>${env.NEXUS_USER}</username><password>${env.NEXUS_TOKEN}</password></server>
</servers>
</settings>
Key points to cover:
pom.xml. Keep them in settings.xml, encrypted with Maven's password encryption, or injected from environment variables or CI secrets.Short answer:
-Dmaven.ext.class.path profilers or the Gradle Enterprise / Develocity build scans for Maven show where the time goes.SNAPSHOT update checks (-nsu), misconfigured mirrors.git bisect on build time, if needed).Then fix the biggest item, and track build time as a metric in CI.
Common trap: jumping straight to mvn -X. Debug logs are huge. Per-module and per-plugin timing tells you where to look first.
Short answer: Bind quality plugins to the lifecycle, and fail the build on violations:
spotless:apply, verifies with spotless:check).check.Key points to cover:
validate), and the slower analysis in verify. Keep the rule sets in a shared parent POM, so every service uses the same standards.dependency:tree, and why is it useful?Short answer: mvn dependency:tree prints the resolved dependency graph: every direct and transitive dependency, its version and scope. It's useful for:
-Dincludes=groupId:artifactId);-Dverbose shows omitted duplicates, and why, for example "omitted for conflict with 2.17.0");mvn dependency:tree -Dverbose -Dincludes=com.fasterxml.jackson.core
mvn dependency:tree -DoutputType=dot -DoutputFile=deps.dot # visualise
Short answer: First check whether you truly need it: a newer compatible release, a patch backport or an alternative library may exist. If you must have two incompatible versions:
maven-shade-plugin <relocations>. The copy then lives in a different package, and doesn't clash with the main version.When it's simply a version choice, pin the version with dependencyManagement, add the needed exclusions, and cover the risky integration with tests.
Key points to cover:
Q: What are Maven extensions, and when do you need them?
A: Extensions (in .mvn/extensions.xml) hook into Maven's core. Examples are the build cache, custom wagons/transports, and Develocity build scans. They're for things plugins can't do.
Q: How do you make Maven builds reproducible?
A: Set project.build.outputTimestamp, pin all plugin versions, avoid dynamic versions, and use the wrapper. Then verify by building twice, and comparing the checksums of the artifacts.
Q: What's the difference between mvn install and mvn deploy?
A: install copies the artifact into your local repository (~/.m2). deploy uploads it to a remote repository, configured in distributionManagement, for others to use.
Q: What does the Maven Wrapper give you?
A: A mvnw script plus .mvn/wrapper properties, which download and use the project's pinned Maven version. Every developer and CI job then uses the same Maven, with no installation needed.