Welcome to our comprehensive tutorial on building a Maven archetype for a Jakarta EE project! In this step-by-step guide, we will empower you with the knowledge and skills to create a powerful foundation for your enterprise applications. With our expert guidance, you’ll master the process of designing a customizable archetype that adheres to best practices and accelerates your development workflow. Let’s dive into this essential tutorial and take your Jakarta EE projects to new heights!
Anatomy of a Maven archetype
Basically a Maven archetype is made up of the following elements:
- An archetype descriptor (archetype-metadata.xml in directory: src/main/resources/META-INF/maven/). It lists all properties and the directories which contain the archetype files.
- The prototype files which are copied by the archetype plugin (directory: src/main/resources/archetype-resources/).
- The prototype pom (pom.xml in: src/main/resources/archetype-resources).
- The pom for the archetype (pom.xml in the archetype’s root directory).
The good news is that you don’t need to create this structure by yourself. You can create it from an archetype follow as follows:
mvn -B archetype:generate -DarchetypeArtifactId=maven-archetype-archetype \ -DarchetypeGroupId=maven-archetype \ -DgroupId=com.mastertheboss -DartifactId=wildfly-archetype
Here is the Maven project, which includes the skeleton we will use to define our archetype:
wildfly-project/ ├── pom.xml └── src ├── main │ └── resources │ ├── archetype-resources │ │ ├── pom.xml │ │ └── src │ │ ├── main │ │ │ └── java │ │ │ └── App.java │ │ └── test │ │ └── java │ │ └── AppTest.java │ └── META-INF │ └── maven │ └── archetype-metadata.xml └── test └── resources └── projects └── it-basic ├── archetype.properties └── goal.txt
Let’s customize the basic archetype
First off, let’s remove the App.java and AppTest.java which will not be part of our project. Then, let’s define the pom.xml for the archetype (top’s pom.xml):
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mastertheboss.archetypes</groupId> <artifactId>jakarta-ee10-archetype</artifactId> <version>1.0.0</version> <name>jakarta-ee10-archetype</name> <packaging>maven-archetype</packaging> <description>Archetype used to generate a sample Jakarta EE 10 application</description> <properties> <archetype-packaging.version>3.0.1</archetype-packaging.version> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> <build> <extensions> <extension> <groupId>org.apache.maven.archetype</groupId> <artifactId>archetype-packaging</artifactId> <version>3.2.0</version> </extension> </extensions> <finalName>${project.artifactId}</finalName> </build> </project>
Next, let’s add the prototype pom which contains the actual WildFly tools and Jakarta EE dependencies:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>${groupId}</groupId> <artifactId>${artifactId}</artifactId> <version>${version}</version> <packaging>war</packaging> <properties> <jakartaee.version>10.0.0</jakartaee.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <failOnMissingWebXml>false</failOnMissingWebXml> <version.server.bom>${version-wildfly}</version.server.bom> <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.wildfly.bom</groupId> <artifactId>wildfly-ee-with-tools</artifactId> <version>${version.server.bom}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.wildfly.bom</groupId> <artifactId>wildfly-microprofile</artifactId> <version>${version.server.bom}</version> <scope>import</scope> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>jakarta.platform</groupId> <artifactId>jakarta.jakartaee-api</artifactId> <version>${jakartaee.version}</version> <scope>provided</scope> </dependency> </dependencies> <build> <finalName>${artifactId}</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.1</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <source>11</source> <target>11</target> <compilerArguments> <endorseddirs>${endorsed.dir}</endorseddirs> </compilerArguments> </configuration> </plugin> <plugin> <groupId>org.wildfly.plugins</groupId> <artifactId>wildfly-maven-plugin</artifactId> <version>2.0.0.Final</version> </plugin> </plugins> </build> </project>
Next, within the archetype-metadata.xml, define the fileset which includes the project source code. In our example, the archetype will pick up files from the src/main/java directory:
<archetype-descriptor 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 http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0" xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="wildfly"> <requiredProperties> <requiredProperty key="version-wildfly"> <defaultValue>28.0.0.Final</defaultValue> </requiredProperty> </requiredProperties> <fileSets> <fileSet filtered="true" packaged="true"> <directory>src/main/java</directory> <includes> <include>**/*.java</include> </includes> </fileSet> </fileSets> </archetype-descriptor>
Here are a few important tags and their purpose:
- Required Property can be used to define properties that can be injected in the prototype pom. In our case “wildfly-version” will be prompted if running in interactive mode.
- FileSet defines how to use the project files located in the jar file to generate a project. If a file or a directory name contains __property__ pattern, it is replaced with corresponding property value
- packaged = “true” means that the selected files will be generated in a directory structure that is prepended by the package property
Finally, let’s add the Java class files, which are added in src/main/resources/archetype-resources/src/main/java. Here is AppConfig.java:
package ${package}; import jakarta.ws.rs.ApplicationPath; import jakarta.ws.rs.core.Application; @ApplicationPath("/rest") public class AppConfig extends Application { }
And here is the HelloREST.java file:
package ${package}; import jakarta.enterprise.context.RequestScoped; import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.UriBuilder; @Path("/hello") public class HelloREST { @GET public Response hello(){ return Response .ok( "Hello World") .build(); } }
This is the final structure of your Archetype project:
src └── main └── resources ├── archetype-resources │ ├── pom.xml │ └── src │ └── main │ └── java │ ├── AppConfig.java │ └── HelloREST.java ├── logback.xml └── META-INF └── maven └── archetype-metadata.xml
You need to install the archetype on your local repository with:
$ mvn clean install
Using the archetype to create a WildFly project
We will now create a sample project using our archetype. First of all, let’s move into another directory, to avoid conflicts with the pom.xml file used by our archetype:
$ mkdir demo $ cd demo
Next, in order to use our archetype, we will refer to the com.mastertheboss.archetypes which is in our local repository:
mvn archetype:generate -DarchetypeGroupId=com.mastertheboss.archetypes -DarchetypeArtifactId=jakarta-ee10-archetype -DarchetypeVersion=1.0.0 -DgroupId=com.example -DartifactId=demo-rest -Dversion=1.0.0
The, at the prompt, confirm or modify the archetype default properties:
[INFO] Using property: version-wildfly = 28.0.0.Final [INFO] Using property: groupId = com.example [INFO] Using property: artifactId = demo-rest [INFO] Using property: version = 1.0.0 [INFO] Using property: package = com.example Confirm properties configuration: version-wildfly: 28.0.0.Final groupId: com.example artifactId: demo-rest version: 1.0.0 package: com.example Y: : Y
Finally, here is the project demo-rest which includes the JAX-RS Activator and a sample Endpoint:
Build and install it with:
$ mvn clean install wildfly:deploy
Test it with:
curl http://localhost:8080/demo-rest/rest/hello Hello World
Conclusion
This article was a quick walk through Maven archetypes creation. We have learnt how to create a Java Enterprise project using WildFly dependencies from a custom Maven archetype.
You can find the source code for it here: https://github.com/fmarchioni/mastertheboss/tree/master/maven-archetype/jakarta-ee10