Mastering Maven: How to Create Your Own Custom Archetypes

Every time you run mvn archetype:generate, Maven reads a blueprint called an archetype to scaffold your project structure. The built-in archetypes cover plain Java and simple web apps, but when your team has its own folder conventions, preferred dependencies, or boilerplate code, you need a custom archetype. In this guide you will build a complete custom Maven archetype from scratch, install it to your local repository, generate a new project from it, and optionally deploy it to a team-shared repository so your whole organisation can use it in one command.

How Maven Archetypes Work

An archetype is itself a Maven project with a special structure. When you invoke archetype:generate, Maven reads a descriptor file (archetype-metadata.xml) to discover which files to copy, and applies Velocity template variables (like ${packageName} and ${artifactId}) to produce the new project.

Step 1: Create the Archetype Project

Bootstrap the archetype project using Maven’s own archetype archetype:

mvn archetype:generate 
  -DarchetypeGroupId=org.apache.maven.archetypes 
  -DarchetypeArtifactId=maven-archetype-archetype 
  -DarchetypeVersion=1.4 
  -DgroupId=com.ankurm.archetypes 
  -DartifactId=spring-boot-microservice-archetype 
  -Dversion=1.0.0 
  -DinteractiveMode=false

This generates a skeleton with the following layout:

spring-boot-microservice-archetype/
  pom.xml
  src/
    main/
      resources/
        META-INF/
          maven/
            archetype-metadata.xml
        archetype-resources/
          pom.xml
          src/
            main/java/
              App.java
            test/java/
              AppTest.java

Step 2: Edit the Archetype pom.xml

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.ankurm.archetypes</groupId>
  <artifactId>spring-boot-microservice-archetype</artifactId>
  <version>1.0.0</version>
  <packaging>maven-archetype</packaging>
  <name>Spring Boot Microservice Archetype</name>

  <build>
    <extensions>
      <extension>
        <groupId>org.apache.maven.archetype</groupId>
        <artifactId>archetype-packaging</artifactId>
        <version>3.2.1</version>
      </extension>
    </extensions>
  </build>
</project>

Step 3: Write the archetype-metadata.xml

This descriptor tells Maven which files to include and which Velocity properties to define:

<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor
    xmlns="https://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.1.0"
    name="spring-boot-microservice">

  <!-- Properties the user is prompted for (or passes via -D) -->
  <requiredProperties>
    <requiredProperty key="javaVersion">
      <defaultValue>21</defaultValue>
    </requiredProperty>
    <requiredProperty key="springBootVersion">
      <defaultValue>3.3.0</defaultValue>
    </requiredProperty>
  </requiredProperties>

  <fileSets>
    <!-- Main Java sources (package directory created automatically) -->
    <fileSet filtered="true" packaged="true">
      <directory>src/main/java</directory>
      <includes>
        <include>**/*.java</include>
      </includes>
    </fileSet>

    <!-- Test sources -->
    <fileSet filtered="true" packaged="true">
      <directory>src/test/java</directory>
      <includes>
        <include>**/*.java</include>
      </includes>
    </fileSet>

    <!-- application.properties template -->
    <fileSet filtered="true">
      <directory>src/main/resources</directory>
      <includes>
        <include>**/*.properties</include>
      </includes>
    </fileSet>
  </fileSets>

</archetype-descriptor>

Step 4: Add Template Files

All files inside archetype-resources/ become templates. Variables in ${...} are substituted at generation time.

archetype-resources/pom.xml

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>${groupId}</groupId>
  <artifactId>${artifactId}</artifactId>
  <version>${version}</version>
  <packaging>jar</packaging>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>${springBootVersion}</version>
  </parent>

  <properties>
    <java.version>${javaVersion}</java.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

archetype-resources/src/main/java/Application.java

#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
package ${package};

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

archetype-resources/src/main/resources/application.properties

spring.application.name=${artifactId}
server.port=8080
logging.level.root=INFO

Step 5: Install the Archetype Locally

cd spring-boot-microservice-archetype
mvn clean install

Maven installs the archetype JAR to ~/.m2/repository and registers it in your local catalog (~/.m2/repository/archetype-catalog.xml).

Step 6: Generate a New Project from Your Archetype

mvn archetype:generate 
  -DarchetypeGroupId=com.ankurm.archetypes 
  -DarchetypeArtifactId=spring-boot-microservice-archetype 
  -DarchetypeVersion=1.0.0 
  -DarchetypeCatalog=local 
  -DgroupId=com.mycompany 
  -DartifactId=payment-service 
  -Dversion=1.0.0-SNAPSHOT 
  -Dpackage=com.mycompany.payment 
  -DjavaVersion=21 
  -DspringBootVersion=3.3.0 
  -DinteractiveMode=false

Maven generates the following ready-to-run project:

payment-service/
  pom.xml                          (Spring Boot parent applied, java 21)
  src/
    main/
      java/com/mycompany/payment/
        Application.java
      resources/
        application.properties     (spring.application.name=payment-service)
    test/
      java/com/mycompany/payment/
        ApplicationTest.java

Sharing the Archetype with Your Team

To share across a team, deploy the archetype to your internal Maven repository (Nexus or Artifactory):

mvn deploy -DaltDeploymentRepository=company-releases::default::https://nexus.company.com/repository/releases/

Team members then run archetype:generate pointing at the remote repository URL and the archetype is pulled automatically — no manual steps required.

Velocity Template Tips

  • Use #set( $symbol_dollar = '$' ) at the top of Java template files to avoid Velocity treating Spring EL expressions like ${spring.datasource.url} as variables.
  • Use filtered="true" on a <fileSet> to enable variable substitution; use filtered="false" for binary resources like images.
  • Use packaged="true" to tell Maven to create subdirectories matching the package name automatically.

See Also

Conclusion

Creating a custom Maven archetype takes about 30 minutes but pays dividends every time a new microservice, library, or module is bootstrapped by anyone on your team. The archetype encodes your organisation’s decisions about folder structure, parent POM, coding standards, and boilerplate configuration — turning a tedious setup task into a single command. Once the archetype is in your Nexus or Artifactory instance, every developer can generate a perfectly structured, standards-compliant project without touching a single configuration file manually.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.