skip to content

How do you wire the maven-toolchains-plugin into a build, and how do you verify which JDK was actually selected?

level: middleimportance: should knowfreq 30%

answer

  1. execution runs toolchains goal, default phase validate
  2. compiler/surefire auto-use it, no extra config
  3. mvn -t for custom toolchains.xml
  4. -X debug shows chosen jdkHome + executable
  5. assert java.home in a test to prove test JVM

basics

~20 s

Add the maven-toolchains-plugin with an execution that runs the toolchains goal (it binds to validate so it runs first). Run mvn with -X or check the toolchains-goal log line to confirm which jdkHome was chosen.

solid answer

~40 s

You declare the maven-toolchains-plugin in `<build><plugins>` with an `<execution>` that runs the `toolchains` goal; it defaults to the `validate` phase so the JDK is selected before compilation. Inside `<configuration>` you put the `<toolchains><jdk>` requirement (version/vendor). Once selected, toolchain-aware plugins (compiler, surefire, failsafe) automatically use that JDK — you do not configure them separately. To verify: the `toolchains` goal logs which toolchain it found (the jdkHome), and running with `-X` (debug) shows the selected toolchain plus the executable path the compiler/test plugins invoke. You can also point at a specific file with `mvn -t toolchains.xml`, and override the file location per-run. If the goal logs that no toolchain matched, the build fails — that is your signal the requirement or toolchains.xml is wrong.

code

bash · 2 lines
bash
# Use a CI-specific toolchains file and show the selection in debug output
mvn -t ci/toolchains.xml -X clean verify | grep -i toolchain

go deeper

for a junior

Can add the plugin execution with the toolchains goal.

for a middle

Knows the default validate phase, that compiler/surefire auto-consume the selection, and how to point at a custom file with -t.

for a senior

Verifies selection via -X and a java.home assertion; debugs no-match failures.

for a principal

Standardizes CI invocation (-t with a provisioned toolchains.xml) and adds guardrail tests that fail if the wrong JDK runs.

## Binding the plugin The plugin must run early so the JDK is chosen before anything compiles. The `toolchains` goal's default phase is **`validate`** (the very first phase of the default lifecycle), so a minimal execution is enough: ```xml <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-toolchains-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <id>select-jdk</id> <goals><goal>toolchains</goal></goals> </execution> </executions> <configuration> <toolchains> <jdk> <version>[11,12)</version> <vendor>temurin</vendor> </jdk> </toolchains> </configuration> </plugin> </plugins> </build> ``` No extra config is needed on the compiler/surefire plugins — they query Maven's toolchain manager and use the selected JDK automatically. ## Running and overriding - `mvn verify` — runs the build; the `toolchains` goal fires in `validate`. - `mvn -t /path/to/toolchains.xml verify` — use a non-default toolchains file (handy in CI). - `mvn --global-toolchains /etc/toolchains.xml verify` — global file. ## Verifying the selection The `toolchains` goal logs a line naming the chosen toolchain and its `jdkHome`, e.g.: ``` [INFO] --- toolchains:3.1.0:toolchains --- [INFO] Required toolchain: jdk [ version='[11,12)' vendor='temurin' ] [INFO] Found matching toolchain for type jdk: JDK[/opt/jdks/temurin-11] ``` For deeper confirmation run with **`-X`** (debug). The compiler/test logs will show the actual `javac`/`java` executable path under that `jdkHome`. A quick sanity test is a unit test that asserts `System.getProperty("java.version")` or prints `java.home` during the Surefire run — that proves the *test JVM* is the toolchain JDK, not Maven's JVM. ## Failure signal If no entry matches, you get: ``` [ERROR] Cannot find matching toolchain definitions for the following toolchain types: jdk [ version='[11,12)' vendor='temurin' ] ``` and the build stops in `validate`. Fix by adding/correcting the `toolchains.xml` entry (watch vendor string spelling and version range) — failing fast here is the intended safety net.

  • Do you have to configure the compiler plugin to use the toolchain?
    No. Toolchain-aware plugins (compiler, surefire, failsafe) automatically use the selected JDK once the toolchains goal has run; no per-plugin wiring is needed.
  • How can you prove your tests actually ran on the toolchain JDK and not Maven's JVM?
    Add a test that logs/asserts System.getProperty("java.home") or java.version during the Surefire run; it should report the toolchain JDK's path/version.

saying these in an interview costs you the question

  • Binding the toolchains goal to a late phase like package — it must run before compile (validate) or the JDK selection has no effect.
  • Thinking each toolchain-aware plugin needs explicit jdkHome configuration.

context