Maven Archetypes: Simplifying Project Template Creation
Maven Archetypes enables you to apply best practices within your project or org. Learn how to create archetypes from scratch and based on an existing project.
Join the DZone community and get the full member experience.
Join For FreeWith Maven Archetypes, you can create a template for your Maven projects. It is a great way to enable and apply best practices within your project or organization. In this blog, you will learn how to create archetypes from scratch and based on an existing project. Enjoy!
Introduction
Maven Archetypes serve as templates for creating Maven projects. Often, you will have some best practices for your organization or team on how to create Maven projects. You can describe these on an intranet or Confluence, but it is even better to create templates for it. And that is what Maven Archetypes can do for you. You can create templates from scratch or you can create a project first and generate a template from the project. And even more, it is not very complicated. So let’s get started and see how this works!
The sources used in this blog can be found on GitHub.
Prerequisites
Prerequisites for reading this blog are:
- Basic knowledge of Maven
- Basic knowledge of Java and Spring Boot (but not really necessary, though)
Generate Archetype From Scratch
First, let’s see how you can create an archetype from scratch. Execute the following command:
$ mvn archetype:generate
A lot of information is dumped into the console, and it ends with the following question:
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 2154:
What should you do with that? When you closely take a look at what has been dumped into the console, then you realize that it is a list of possible archetypes to choose from. Each one has a unique number attached. When you browse the list that has been dumped to the console, you can find the maven-archetypes
list.
2146: remote -> org.apache.maven.archetypes:maven-archetype-archetype (An archetype which contains a sample archetype.)
2147: remote -> org.apache.maven.archetypes:maven-archetype-j2ee-simple (An archetype which contains a simplified sample J2EE application.)
2148: remote -> org.apache.maven.archetypes:maven-archetype-marmalade-mojo (-)
2149: remote -> org.apache.maven.archetypes:maven-archetype-mojo (An archetype which contains a sample a sample Maven plugin.)
2150: remote -> org.apache.maven.archetypes:maven-archetype-plugin (An archetype which contains a sample Maven plugin.)
2151: remote -> org.apache.maven.archetypes:maven-archetype-plugin-site (An archetype which contains a sample Maven plugin site. This archetype can be layered upon an
existing Maven plugin project.)
2152: remote -> org.apache.maven.archetypes:maven-archetype-portlet (An archetype which contains a sample JSR-268 Portlet.)
2153: remote -> org.apache.maven.archetypes:maven-archetype-profiles (-)
2154: remote -> org.apache.maven.archetypes:maven-archetype-quickstart (An archetype which contains a sample Maven project.)
2155: remote -> org.apache.maven.archetypes:maven-archetype-simple (An archetype which contains a simple Maven project.)
2156: remote -> org.apache.maven.archetypes:maven-archetype-site (An archetype which contains a sample Maven site which demonstrates some of the supported document types like
APT, XDoc, and FML and demonstrates how to i18n your site. This archetype can be layered
upon an existing Maven project.)
2157: remote -> org.apache.maven.archetypes:maven-archetype-site-simple (An archetype which contains a sample Maven site.)
2158: remote -> org.apache.maven.archetypes:maven-archetype-site-skin (An archetype which contains a sample Maven Site Skin.)
2159: remote -> org.apache.maven.archetypes:maven-archetype-webapp (An archetype which contains a sample Maven Webapp project.)
You are looking to create a project for an archetype, this would be number 2146. You can enter this number, but you could also have entered a filter like maven-archetype-archetype
which will limit the results.
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 128: maven-archetype-archetype
Choose archetype:
1: remote -> org.apache.maven.archetypes:maven-archetype-archetype (An archetype which contains a sample archetype.)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): :
Now there is only one result, choose 1 and press enter.
The next question to answer is which version of the archetype you want to use. By default, the most recent one is selected. This is the one you will use, so just press enter.
Choose org.apache.maven.archetypes:maven-archetype-archetype version:
1: 1.0-alpha-4
2: 1.0
3: 1.3
4: 1.4
Choose a number: 4:
At last, you need to enter the groupId
, artifactId
, version
and package
. You will be presented with a summary and after pressing enter, the archetype project is created.
Define value for property 'groupId': com.mydeveloperplanet
Define value for property 'artifactId': myfirstarchetype
Define value for property 'version' 1.0-SNAPSHOT: :
Define value for property 'package' com.mydeveloperplanet: :
Confirm properties configuration:
groupId: com.mydeveloperplanet
artifactId: myfirstarchetype
version: 1.0-SNAPSHOT
package: com.mydeveloperplanet
Y: :
Let’s take a look at the generated archetype project.
Pom
The root of the repository contains a pom file. The GAV (groupId
, artifactId
and version
) are present, just like entered during the template generation. The most interesting about this pom is that it contains the packaging type maven-archetype
.
<groupId>com.mydeveloperplanet</groupId>
<artifactId>myfirstarchetype</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>maven-archetype</packaging>
<name>Archetype - myfirstarchetype</name>
Archetype Descriptor
The Archetype Descriptor is a file containing the files that should be included when generating a project from the archetype. The Archetype Descriptor is found in file src/main/resources/META-INF/maven/archetype-metadata.xml
. As can be seen in this file, the files contained in directories src/main/java
and src/test/java
will be included.
<archetype-descriptor xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd"
name="${artifactId}">
<fileSets>
<fileSet filtered="true" packaged="true">
<directory>src/main/java</directory>
</fileSet>
<fileSet filtered="true" packaged="true">
<directory>src/test/java</directory>
</fileSet>
</fileSets>
</archetype-descriptor>
Prototype Files
The files to be included in a generated project are present in the directory src/main/resources/archetype-sources/
.
The pom contains some placeholders for the GAV-parameters which need to be filled during project generation.
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
The only source file in this project also contains a placeholder for the package name.
package $package;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}
Install the Archetype
Before you can start using the archetype, you must install it in at least your local Maven repository. If you want to share it with your colleagues, you will need to deploy it to a Maven repository.
Execute the following command to do so:
$ mvn install
A compilation error occurs:
[INFO] [INFO] -------------------------------------------------------------
[INFO] [ERROR] COMPILATION ERROR :
[INFO] [INFO] -------------------------------------------------------------
[INFO] [ERROR] Source option 7 is no longer supported. Use 8 or later.
[INFO] [ERROR] Target option 7 is no longer supported. Use 8 or later.
[INFO] [INFO] 2 errors
[INFO] [INFO] -------------------------------------------------------------
Change the used Java version in src/main/resources/archetype-resources/pom.xml
. For consistency, also change it in the pom.xml in the root of the repository.
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
The archetype is installed in the local Maven repository and is ready to be used.
Generate Project From Archetype
In order to generate a project from the archetype, you can again use the interactive mode and execute the command mvn archetype:generate
, just like you did before. You can select your newly created archetype from the list and continue. However, you can also provide some parameters to the command. You can specify which archetype you want to use and which groupId
and artifactId
you want to use.
$ mvn archetype:generate \
-DarchetypeGroupId=com.mydeveloperplanet \
-DarchetypeArtifactId=myfirstarchetype \
-DarchetypeVersion=1.0-SNAPSHOT \
-DgroupId=com.mydeveloperplanet \
-DartifactId=myfirstproject
You will be asked which version you want, just press enter to confirm the default.
Define value for property 'version' 1.0-SNAPSHOT: :
In the end, the generation is completed successfully.
$ mvn archetype:generate \
-DarchetypeGroupId=com.mydeveloperplanet \
-DarchetypeArtifactId=myfirstarchetype \
-DarchetypeVersion=1.0-SNAPSHOT \
-DgroupId=com.mydeveloperplanet \
-DartifactId=myfirstproject
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] >>> archetype:3.2.1:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO]
[INFO] <<< archetype:3.2.1:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO]
[INFO]
[INFO] --- archetype:3.2.1:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] Archetype repository not defined. Using the one from [com.mydeveloperplanet:myfirstarchetype:1.0-SNAPSHOT] found in catalog local
[INFO] Using property: groupId = com.mydeveloperplanet
[INFO] Using property: artifactId = myfirstproject
Define value for property 'version' 1.0-SNAPSHOT: :
[INFO] Using property: package = com.mydeveloperplanet
Confirm properties configuration:
groupId: com.mydeveloperplanet
artifactId: myfirstproject
version: 1.0-SNAPSHOT
package: com.mydeveloperplanet
Y: :
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: myfirstarchetype:1.0-SNAPSHOT
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.mydeveloperplanet
[INFO] Parameter: artifactId, Value: myfirstproject
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.mydeveloperplanet
[INFO] Parameter: packageInPathFormat, Value: com/mydeveloperplanet
[INFO] Parameter: package, Value: com.mydeveloperplanet
[INFO] Parameter: groupId, Value: com.mydeveloperplanet
[INFO] Parameter: artifactId, Value: myfirstproject
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Project created from Archetype in dir: /<home directory>/MyMavenArchetypesPlanet/myfirstproject
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 47.869 s
[INFO] Finished at: 2024-06-08T15:34:26+02:00
[INFO] ------------------------------------------------------------------------
The pom is created based on the pom provided and the placeholders are replaced.
<groupId>com.mydeveloperplanet</groupId>
<artifactId>myfirstproject</artifactId>
<version>1.0-SNAPSHOT</version>
The class App.java
is present in package com.mydeveloperplanet
and also here the placeholder for the package is replaced with its actual value.
package com.mydeveloperplanet;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}
Build the project and it will be succesful. You are now up and running to start coding!
$ mvn clean verify
Generate Archetype From Existing Project
Instead of creating an archetype from scratch, you can also create an archetype based on an existing project. In that case, you can create the project first, just like you want it to be, and then create an archetype from it. In order to demonstrate this, a basic Spring Boot application is created via the Spring Initialzr and the Web dependency is added. The project is present in directory myspringbasicproject
.
Execute the following command from within this project directory in order to generate the archetype files.
$ mvn archetype:create-from-project
Navigate to directory target/generated-sources/archetype
and you will find the archetype project files.
When you take a look at the Archetype Descriptor, you will notice that more files are included. You should check whether this is correct and adjust accordingly.
<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor xsi:schemaLocation="https://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.1.0 http://maven.apache.org/xsd/archetype-descriptor-1.1.0.xsd" name="myspringbasicproject"
xmlns="https://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<fileSets>
<fileSet filtered="true" packaged="true" encoding="UTF-8">
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
</includes>
</fileSet>
<fileSet filtered="true" packaged="true" encoding="UTF-8">
<directory>src/test/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>.mvn/wrapper</directory>
<includes>
<include>**/*.properties</include>
</includes>
</fileSet>
<fileSet encoding="UTF-8">
<directory></directory>
<includes>
<include>HELP.md</include>
<include>.gitignore</include>
<include>mvnw</include>
<include>mvnw.cmd</include>
</includes>
</fileSet>
</fileSets>
</archetype-descriptor>
The archetype-resources
directory contains the project files again, just like before, and contains some placeholders to be filled during generation.
Copy the pom.xml
and src
directory of directory target/generated-sources/archetype
to a new directory myspringbasicprojectarchetype
.
Invoke the following command from within directory myspringbasicprojectarchetype
in order to install the archetype to your local Maven repository.
$ mvn install
Generate Project From Archetype
Again, time to generate a project from the newly created archetype. From the root of the repository, invoke the following command. Note that you also include the package name as an argument, otherwise the application will be located in the default package com.mydeveloperplanet
.
$ mvn archetype:generate \
-DarchetypeGroupId=com.mydeveloperplanet \
-DarchetypeArtifactId=myspringbasicproject-archetype \
-DarchetypeVersion=0.0.1-SNAPSHOT \
-DgroupId=com.mydeveloperplanet \
-DartifactId=myspringbasicprojectgenerated \
-Dpackage=com.mydeveloperplanet.myspringbasicprojectgenerated
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] >>> archetype:3.2.1:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO]
[INFO] <<< archetype:3.2.1:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO]
[INFO]
[INFO] --- archetype:3.2.1:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] Archetype repository not defined. Using the one from [com.mydeveloperplanet:myspringbasicproject-archetype:0.0.1-SNAPSHOT] found in catalog local
[INFO] Using property: groupId = com.mydeveloperplanet
[INFO] Using property: artifactId = myspringbasicprojectgenerated
Define value for property 'version' 1.0-SNAPSHOT: :
[INFO] Using property: package = com.mydeveloperplanet.myspringbasicprojectgenerated
Confirm properties configuration:
groupId: com.mydeveloperplanet
artifactId: myspringbasicprojectgenerated
version: 1.0-SNAPSHOT
package: com.mydeveloperplanet.myspringbasicprojectgenerated
Y: :
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: myspringbasicproject-archetype:0.0.1-SNAPSHOT
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.mydeveloperplanet
[INFO] Parameter: artifactId, Value: myspringbasicprojectgenerated
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.mydeveloperplanet.myspringbasicprojectgenerated
[INFO] Parameter: packageInPathFormat, Value: com/mydeveloperplanet/myspringbasicprojectgenerated
[INFO] Parameter: package, Value: com.mydeveloperplanet.myspringbasicprojectgenerated
[INFO] Parameter: groupId, Value: com.mydeveloperplanet
[INFO] Parameter: artifactId, Value: myspringbasicprojectgenerated
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Project created from Archetype in dir: /<home directory>/MyMavenArchetypesPlanet/myspringbasicprojectgenerated
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9.181 s
[INFO] Finished at: 2024-06-08T13:53:06+02:00
[INFO] ------------------------------------------------------------------------
The project is generated in directory myspringbasicprojectgenerated
and contains all the files and the project structure as expected.
Build the project from within the directory.
$ mvn clean verify
Conclusion
Maven Archetypes is very convenient way to create project templates for your team or organization. Especially creating templates from existing projects is a powerful feature.
Published at DZone with permission of Gunter Rotsaert, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments