skip to content

How do you author a custom archetype, and what is the role of archetype-metadata.xml?

level: seniorimportance: should knowfreq 30%

answer

  1. packaging maven-archetype
  2. archetype-resources/ holds the templated files
  3. META-INF/maven/archetype-metadata.xml descriptor
  4. fileSet filtered (Velocity) + packaged (under package)
  5. create-from-project to bootstrap

basics

~10 s

Create 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 s

A 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
xml
<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

for a junior

Aware that custom archetypes exist and are built like a normal Maven artifact.

for a middle

Can lay out archetype-resources and a basic descriptor and install it.

for a senior

Designs requiredProperties, filtered/packaged file sets, escapes literal $, and bootstraps via create-from-project with integration tests.

for a principal

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.

context