1. Overview
A Maven archetype is an abstraction of a kind of a project that can be instantiated into a concrete customized Maven project. In short, it’s a template project template from which other projects are created.
The main benefit of using archetypes is to standardize project development and to enable developers to easily follow best practices while bootstrapping their projects faster.
In this tutorial, we’ll look at how to create a custom archetype and then how to use it to generate a Maven project through the maven-archetype-plugin.
2. Maven Archetype Descriptor
The Maven archetype descriptor is the heart of the archetype project. It’s an XML file named archetype-metadata.xml and located in the META-INF/maven directory of the jar.
It’s used to describe archetypes’ metadata:
<archetype-descriptor ... name="custom-archetype"> <requiredProperties> <requiredProperty key="foo"> <defaultValue>bar</defaultValue> </requiredProperty> </requiredProperties> <fileSets> <fileSet filtered="true" packaged="true"> <directory>src/main/java</directory> <includes> <include>**/*.java</include> </includes> </fileSet> </fileSets> <modules> <module name="sub-module"></module> </modules> </archetype-descriptor>
The requiredProperties tag is used for providing properties during project generation. Thus, we’ll be prompted to provide values for them, with the choice to accept the default value.
fileSets, on the other hand, are used to configure which resources will be copied into the concrete generated project. A filtered file means that placeholders will be substituted with provided values during the generation process.
And, by using packaged=”true” in the fileSet, we’re saying that selected files will be added to the folder hierarchy specified by the package property.
If we want to generate a multi-module project, then the tag modules can help to configure all modules of the generated project.
Note that this file is about Archetype 2 and above. In the version 1.0.x, the file was just called archetype.xml and it had a different structure.
For more information, definitely have a look at the official Apache docs.
3. How to Create an Archetype
An archetype is a normal Maven project with the following extra content:
- src/main/resources/archetype-resources is the template from which resources are copied to the newly created project
- src/main/resources/META-INF/maven/archetype-metadata.xml: is the descriptor used to describe archetypes’ metadata
To create an archetype manually, we can start with a newly created Maven project and then we can add the resources mentioned above.
Or, we can generate it by using the archetype-maven-plugin, and then customize the content of the archetype-resources directory and archetype-metadata.xml file.
To generate the archetype, we can use:
mvn archetype:generate -B -DarchetypeArtifactId=maven-archetype-archetype
We can also create the archetype from an existing Maven project:
mvn archetype:create-from-project
It’s generated in target/generated-sources/archetype, ready to be used.
No matter how we’ve created the archetype, we’ll end up with the following structure:
archetype-root/ ├── pom.xml └── src └── main ├── java └── resources ├── archetype-resources │ ├── pom.xml │ └── src └── META-INF └── maven └── archetype-metadata.xml
We can now start building our archetype by putting resources in the archetype-resources directory and configuring them in the archetype-metadata.xml file.
4. Building the Archetype
Now we’re ready to customize our archetype. For the highlight of this process, we’re going to showcase the creation of a simple Maven archetype for generating a RESTful application based on JAX-RS 2.1.
Let’s just call it maven-archetype.
4.1. Archetype Packaging
Let’s start by modifying the pom.xml of the archetype project located under the maven-archetype directory:
<packaging>maven-archetype</packaging>
This type of packaging is available thanks to the archetype-packaging extension:
<build> <extensions> <extension> <groupId>org.apache.maven.archetype</groupId> <artifactId>archetype-packaging</artifactId> <version>3.0.1</version> </extension> </extensions> <!--....--> </build>
4.2. Adding the pom.xml
Let’s now create a pom.xml file located under the archetype-resources directory:
<project ...> <groupId>${groupId}</groupId> <artifactId>${artifactId}</artifactId> <version>${version}</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>javax.ws.rs</groupId> <artifactId>javax.ws.rs-api</artifactId> <version>2.1</version> <scope>provided</scope> </dependency> </dependencies> </project>
As we can see, groupId, artifactId and version are parameterized. They will be replaced during the creation of a new project from this archetype.
We can put everything needed by the generated project, like dependencies and plugins, in the pom.xml. Here, we’ve added the JAX RS dependency as the archetype will be used for generating RESTful based application.
4.3. Adding Required Resources
Next, we can add some Java code for our application in archetype-resources/src/main/java.
A class for configuring JAX-RS application:
package ${package}; // import @ApplicationPath("${app-path}") public class AppConfig extends Application { }
And a class for a ping resource:
@Path("ping") public class PingResource{ //... }
Finally, put the server configuration file, server.xml, in archetype-resources/src/main/config/liberty.
4.4. Configuring Metadata
After adding all needed resources, we can now configure which ones will be copied during generation through the archetype-metadata.xml file.
We can tell our archetype that we want all Java source files to be copied:
<archetype-descriptor name="maven-archetype"> <!--...--> <fileSets> <fileSet filtered="true" packaged="true"> <directory>src/main/java</directory> <includes> <include>**/*.java</include> </includes> </fileSet> <fileSet> <directory>src/main/config/liberty</directory> <includes> <include>server.xml</include> </includes> </fileSet> </fileSets> </archetype-descriptor>
Here, we want all Java files from src/main/java directory, and the server.xml file from src/main/config/liberty, to be copied.
4.5. Installing the Archetype
Now that we’ve finished putting it all together, we can install the archetype by invoking this command:
mvn install
At this point, the archetype is registered in the file archetype-catalog.xml, located in Maven local repository, and therefore ready for use.
5. Using the Installed Archetype
The maven-archetype-plugin allows the user to create a Maven project through the generate goal and existing archetype. For more information on this plugin, you can visit the homepage.
This command uses this plugin to generate a Maven project from our archetype:
mvn archetype:generate -DarchetypeGroupId=com.baeldung.archetypes -DarchetypeArtifactId=maven-archetype -DarchetypeVersion=1.0-SNAPSHOT -DgroupId=com.baeldung.restful -DartifactId=cool-jaxrs-sample -Dversion=1.0-SNAPSHOT
We should then pass the GAV of our archetype as arguments to the maven-archetype-plugin:generate goal. We can also pass the GAV of the concrete project that we want to generate, otherwise, we can provide them in interactive mode.
The concrete cool-jaxrs-sample generated project is therefore ready to run without any changes. So, we can run it by just invoking this command:
mvn package liberty:run
We can then access this URL:
http://localhost:9080/cool-jaxrs-sample/<app-path>/ping
6. Conclusion
In this article, we’ve showcased how to build and use a Maven archetype.
We’ve demonstrated how to create the archetype and then how to configure the template resources through the archetype-metadata.xml file.
The code, as usual, can be found over on Github.