What is the build-helper-maven-plugin, and what kinds of problems does it solve in a Maven build?
answer
- org.codehaus.mojo
- add-source / attach-artifact
- parse-version / regex-property
- reserve-network-port
- bag of unrelated goals
basics
~10 sIt's a utility plugin that adds small 'glue' goals Maven core lacks: registering extra source/test folders, attaching extra build outputs as artifacts, parsing versions, extracting a property by regex, and reserving free network ports.
solid answer
~40 sThe build-helper-maven-plugin (groupId org.codehaus.mojo) is a collection of small, unrelated utility goals that fill gaps in Maven's fixed convention. The most common are: add-source / add-test-source to register additional source roots (e.g. generated code) so the compiler picks them up; attach-artifact to publish secondary outputs alongside the main JAR; parse-version to split a version into major/minor/incremental properties; regex-property to derive a property by applying a regex; and reserve-network-port to grab free ephemeral ports for integration tests. You bind each goal to a phase via an execution with its own id. It exists because Maven's lifecycle and project model are deliberately rigid — one main artifact, conventional src layout — and these goals let you bend that without writing a custom plugin.
code
xml · 17 lines<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<id>add-generated</id>
<phase>generate-sources</phase>
<goals><goal>add-source</goal></goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/jaxb</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>go deeper
Know it adds extra source folders and exists under the mojohaus groupId; recall add-source by name.
Wire add-source to generate-sources and attach-artifact with a classifier; understand each goal is independent.
Choose between build-helper named goals vs exec/antrun; keep generated code out of src; reserve ports for parallel ITs.
Standardize glue patterns across a multi-module repo; pin plugin versions in pluginManagement; weigh a real custom plugin vs accreting glue.
## What it is Maven enforces a strong convention: each project produces one main artifact, sources live under `src/main/java`, the lifecycle runs a fixed set of phases. The **build-helper-maven-plugin** (Maven coordinates `org.codehaus.mojo:build-helper-maven-plugin`) is a 'Swiss-army-knife' plugin: a bag of small, independent **goals** (a goal = one runnable plugin task) that each patch one limitation of that convention. They share nothing except living in the same plugin. ## The main goals - **add-source** — registers an extra directory as a compile source root, so the `maven-compiler-plugin` also compiles it. Typical use: a folder of code emitted by a code generator (JAXB, protobuf, OpenAPI). Bind it to the `generate-sources` phase. - **add-test-source** — same idea for test sources (bind to `generate-test-sources`). - **add-resource / add-test-resource** — register extra resource directories. - **attach-artifact** — takes an additional file you built and **attaches** it to the project so `install`/`deploy` publish it next to the main artifact, using a `classifier` (e.g. `client`, `tests`) and `type` to keep coordinates unique. - **parse-version** — reads the project version (e.g. `1.4.7-SNAPSHOT`) and sets properties `parsedVersion.majorVersion`, `minorVersion`, `incrementalVersion`, `qualifier`, etc., for downstream filtering or naming. - **regex-property** — sets a new property by applying a regular expression `regex`/`replacement` to a `value`. Useful to sanitize a branch name or strip a suffix. - **reserve-network-port** — finds free TCP ports and assigns them to named properties (e.g. `it.server.port`) so parallel integration-test runs don't collide. Bind it before the servers start (e.g. `process-test-resources` or `pre-integration-test`). ## How you wire it Each goal goes in its own `<execution>` with a unique `<id>`, `<phase>`, `<goals>`, and `<configuration>`. ```xml <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <version>3.6.0</version> <executions> <execution> <id>add-generated-sources</id> <phase>generate-sources</phase> <goals><goal>add-source</goal></goals> <configuration> <sources> <source>${project.build.directory}/generated-sources/openapi</source> </sources> </configuration> </execution> </executions> </plugin> ``` ## Relationship to exec/antrun It is part of the broader 'glue' family with **exec-maven-plugin** (run an external program or a Java main) and **maven-antrun-plugin** (run inline Ant tasks). Reach for build-helper for its specific named goals; reach for exec/antrun for arbitrary one-off steps.
- Why not just put generated code under src/main/java?Generated code should never live under version-controlled source roots — it gets stale, causes merge noise, and is overwritten. You generate it into target/ and use add-source so the compiler still sees it, keeping it out of git.
- What groupId is the plugin under?org.codehaus.mojo (the Mojohaus project), not org.apache.maven.plugins, so it does not get the short prefix-resolution by default unless configured in settings.xml pluginGroups.
It's the junk drawer of Maven plugins — a handful of unrelated little tools (tape, scissors, batteries) that each fix one annoyance the main toolbox doesn't cover.
saying these in an interview costs you the question
- Saying it is part of Maven core or under org.apache.maven.plugins
- Thinking add-source copies files rather than registering a compile root
- Believing one execution can run multiple unrelated goals cleanly without separate ids