Compare core extensions (.mvn/extensions.xml) versus build extensions (<build><extensions>): when does each load, and why does it matter?
answer
- .mvn = bootstrap, before POM parse
- <build> = during parsed-project build
- core realm vs project extension realm
- core: polyglot/smart-builder; build: wagon/packaging
- commit .mvn for reproducibility
basics
~10 sCore extensions in .mvn/extensions.xml load before the POM is read, so they can change project loading itself. Build extensions in <build><extensions> load later, while building an already-parsed project, so they're limited to build-time machinery.
solid answer
~40 sBoth inject components into Maven's runtime, but the timing and classloader differ. Core extensions (.mvn/extensions.xml, Maven 3.3.1+) load during Maven's bootstrap — before any POM is parsed — and join the Maven core realm, so they can replace model readers (polyglot), swap the build sequencer (smart builders), or alter project discovery. Build extensions (<build><extensions>) load once the project model exists, contribute things like wagons, custom packaging/lifecycle, and live in the project's extension realm. The practical consequences: anything that must influence how the project itself is read or sequenced must be a core extension; anything that just augments the build of a normally-parsed project can be a build extension. Core extensions also apply to the whole reactor from the directory they sit in and must be committed so every checkout is reproducible.
code
bash · 5 lines# core extensions live here, loaded before the POM:
# project-root/.mvn/extensions.xml
# build extensions live in the POM:
# <build><extensions><extension>...</extension></extensions></build>
mvn -X validate # use debug output to see extension realms being createdgo deeper
Knows there are two places to declare extensions.
Knows core extensions load earlier than build extensions.
Can map specific use cases to the right mechanism and explain the realm/timing difference.
Sets org policy: which extensions are allowed, ensures .mvn is committed, prefers least-powerful mechanism for reproducible, reviewable builds.
## Two extension entry points Maven wires components (Sisu/Plexus) into **classloader realms**. Extensions add components, but *when* they load and *which realm* they join determines what they can do. ### Core extensions — `.mvn/extensions.xml` - Introduced in Maven **3.3.1**. - Located in the project root's `.mvn/` directory. - Loaded during **bootstrap**, *before any POM is parsed*, into a realm close to the Maven core. - Can therefore influence **project loading and sequencing itself**: custom `ModelReader` (polyglot), `BuildListener`/lifecycle participants, replacement build sequencers (Takari smart builder), provisioning extensions. ```xml <!-- .mvn/extensions.xml --> <extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0"> <extension> <groupId>fr.jcgay.maven</groupId> <artifactId>maven-profiler</artifactId> <version>3.3</version> </extension> </extensions> ``` ### Build extensions — `<build><extensions>` - Declared in the **POM**, so the POM is already parsed when they load. - Loaded into a **project-scoped extension realm** during the build. - Suited to things that operate within a normally-loaded project: **wagons** (transport), **custom packaging + LifecycleMapping**, ArtifactHandlers. ```xml <build> <extensions> <extension> <groupId>org.apache.maven.wagon</groupId> <artifactId>wagon-ftp</artifactId> <version>3.5.3</version> </extension> </extensions> </build> ``` ## Why the distinction matters | Concern | Core ext (.mvn) | Build ext (<build>) | |---|---|---| | Load time | Before POM parse (bootstrap) | During build of parsed project | | Realm | Near Maven core | Project extension realm | | Can change model reading | Yes (polyglot) | No | | Can replace build sequencer | Yes (smart builder) | No | | Typical use | polyglot, profilers, smart builder | wagon, packaging, lifecycle | | Scope | The reactor rooted at that dir | The declaring project | ## Governance / reproducibility - `.mvn/extensions.xml` (and `.mvn/maven.config`/`jvm.config`) should be **committed** so every developer and CI runs the identical machinery — otherwise builds diverge. - Core extensions affect the whole multi-module reactor invoked from that directory, making them a powerful but blunt instrument; review them carefully. - Prefer the least-powerful mechanism: use a build extension if it suffices, reserve core extensions for things that genuinely need early loading.
- Why should .mvn/extensions.xml be committed to version control?So every checkout and CI run loads the same core machinery; otherwise builds become non-reproducible across machines.
- Can a build extension replace Maven's model reader for polyglot?No — it loads after the POM is parsed, too late. Model readers must be core extensions.
- Which extension type can swap the reactor's build sequencer (e.g. Takari smart builder)?A core extension in .mvn/extensions.xml, because it loads early enough to influence sequencing.
saying these in an interview costs you the question
- Claiming both load at the same time / are interchangeable.
- Putting a polyglot or smart-builder extension in <build><extensions>.
- Leaving .mvn/extensions.xml uncommitted and assuming builds stay reproducible.