How do you author a custom archetype, and what is the role of archetype-metadata.xml?
answer
- packaging maven-archetype
- archetype-resources/ holds the templated files
- META-INF/maven/archetype-metadata.xml descriptor
- fileSet filtered (Velocity) + packaged (under package)
- create-from-project to bootstrap
basics
~10 sCreate an archetype project whose template files live under src/main/resources/archetype-resources, and describe them — required properties, file sets, packaged folders — in src/main/resources/META-INF/maven/archetype-metadata.xml. Build and install it like any artifact.
solid answer
~40 sA custom archetype is a Maven project of packaging `maven-archetype`. The template content goes under `src/main/resources/archetype-resources/` — including a `pom.xml` (the *generated* project's POM, with placeholders) and source/resource trees. The descriptor `src/main/resources/META-INF/maven/archetype-metadata.xml` (the Archetype 2.x / 'archetype descriptor' format) declares: `requiredProperties` the user must supply, and `fileSets` that tell the plugin which directories to copy, whether they're **filtered** (placeholders substituted) and whether they're **packaged** (relocated under the user's `package` directory). Placeholders use Velocity syntax like `${groupId}`, `${artifactId}`, `${package}`. The fastest way to start is `mvn archetype:create-from-project` against a working sample, which generates this structure for you. You then `mvn install` (or deploy) the archetype and consumers run `archetype:generate` against its coordinates.
code
xml · 17 lines<archetype-descriptor name="service-archetype">
<requiredProperties>
<requiredProperty key="port">
<defaultValue>8080</defaultValue>
</requiredProperty>
</requiredProperties>
<fileSets>
<fileSet filtered="true" packaged="true" encoding="UTF-8">
<directory>src/main/java</directory>
<includes><include>**/*.java</include></includes>
</fileSet>
<fileSet filtered="true" packaged="false" encoding="UTF-8">
<directory>src/main/resources</directory>
<includes><include>**/*.yml</include></includes>
</fileSet>
</fileSets>
</archetype-descriptor>go deeper
Aware that custom archetypes exist and are built like a normal Maven artifact.
Can lay out archetype-resources and a basic descriptor and install it.
Designs requiredProperties, filtered/packaged file sets, escapes literal $, and bootstraps via create-from-project with integration tests.
Standardizes the org's archetype authoring patterns, versions/deprecates archetypes, and wires archetype:integration-test into CI for template quality.
## What you are building A **custom archetype** is itself a Maven module that produces a template artifact. Its packaging is `maven-archetype`. When someone runs `archetype:generate` with your archetype's coordinates, Maven reads its descriptor and copies/transforms its bundled files into the user's new project. ## Directory layout ``` my-archetype/ pom.xml # the ARCHETYPE's own pom (packaging maven-archetype) src/main/resources/ META-INF/maven/archetype-metadata.xml # the descriptor archetype-resources/ pom.xml # the GENERATED project's pom (templated) src/main/java/App.java src/test/java/AppTest.java ``` Note the two POMs: the outer one builds the archetype; the one under `archetype-resources/` is what ends up in generated projects (so it contains `${groupId}`, `${artifactId}`, `${version}`, `${package}`). ## archetype-metadata.xml — the descriptor This is the Archetype 2.x descriptor (distinct from the legacy `archetype.xml`). It controls generation: ```xml <archetype-descriptor name="service-archetype" xmlns="https://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.1.0"> <requiredProperties> <requiredProperty key="port"> <defaultValue>8080</defaultValue> </requiredProperty> </requiredProperties> <fileSets> <fileSet filtered="true" packaged="true" encoding="UTF-8"> <directory>src/main/java</directory> <includes><include>**/*.java</include></includes> </fileSet> <fileSet filtered="true" packaged="false" encoding="UTF-8"> <directory>src/main/resources</directory> <includes><include>**/*.yml</include></includes> </fileSet> </fileSets> </archetype-descriptor> ``` Key attributes: - **requiredProperties** — extra inputs prompted at generation time (beyond the standard g/a/v/package); may carry `defaultValue`. - **fileSet `filtered`** — `true` runs the files through Velocity so `${...}` placeholders are replaced; `false` copies verbatim (use for binaries or files that legitimately contain `$`). - **fileSet `packaged`** — `true` relocates the directory under the user's chosen package path (e.g. `src/main/java/com/example/myapp/`); `false` keeps the path as-is. ## Placeholder syntax Templating uses **Velocity**: `${groupId}`, `${artifactId}`, `${version}`, `${package}`, plus any `requiredProperty`. To emit a literal `$` you escape it (e.g. `\${...}`), important for Spring/shell files. ## Bootstrapping the easy way `mvn archetype:create-from-project` run inside a finished sample project reverse-engineers the descriptor and `archetype-resources` tree for you under `target/generated-sources/archetype`. You refine it, then build. ## Building and publishing ```bash mvn install # installs the archetype into ~/.m2 mvn deploy # publishes to a shared repository for the team mvn archetype:integration-test # runs projects.properties-driven IT generations ``` Consumers then generate from it via its coordinates or your internal catalog.
- What do the filtered and packaged attributes on a fileSet do?filtered=true runs files through Velocity so ${...} placeholders are substituted; filtered=false copies verbatim. packaged=true relocates the directory under the user's chosen package path; packaged=false leaves the path unchanged.
- How can you quickly bootstrap an archetype from an existing working project?Run mvn archetype:create-from-project inside that project; it generates the archetype-resources tree and archetype-metadata.xml under target/generated-sources/archetype, which you then refine and install.
- How do you parameterize values beyond groupId/artifactId/version?Declare them as <requiredProperty> entries in archetype-metadata.xml (optionally with a defaultValue); the user is prompted for them and you reference them as ${key} in filtered files.
saying these in an interview costs you the question
- Confusing the archetype's own pom (packaging maven-archetype) with the templated pom under archetype-resources.
- Forgetting filtered=true, so placeholders are copied literally instead of substituted.
- Using the legacy archetype.xml descriptor instead of the 2.x META-INF/maven/archetype-metadata.xml.