Overview

Hi guys, in this first post I’ll talk about how to create a basic Maven Archetype from scratch. Having the ability to create an archetype is sometimes needed on our daily basis work, as individuals or working with a company.

 

What is Maven?

Maven is a project from the  Apache Software Foundation and a software management tool, or to be more precise, a project management tool. It provides a way to manage the life cycle of a project’s build process.

Is based on what it’s called a POM (Project Object Model) which describes the project itself, it’s external dependencies, relation with other modules and the order in which will be built or constructed.

One of the advantages of Maven is that it helps to manage all the external dependencies (.jar) in a central repository, so we don’t need to worry about getting every jar one by one and put it into our project manually. Maven will automatically search every dependency described in its pom.xml file, download and add those artifacts to the project. It greatly improves work within a team so everyone will have a homogeneous project configuration.

When it comes to building the project, Maven provides a set of phases that can be executed to achieve some result. It allows you to compile, test, package, install and deploy the project in an easy way.

 

What is an Archetype?

An Archetype is a tool for generating templates for maven projects, or how is defined in the original documentation with a fancy phrase :

an original pattern or model from which all other things of the same kind are made

Very cool definition!. In short, an archetype allows you to define basic projects structures to be reused any time you need to create a new maven project. It helps you to have a template ready to be used on the fly and without too much effort to set it up.

 

Let’s Begin!

We’ll create a basic Spring Boot Application. I know, you can create this with your favorite IDE or use Spring Initializr page, but we’re going to learn how those cool archetypes can be created.

Our final application will have a base controller to accept a request call and a service to provide responses.

Note: Please don’t put much effort understanding the code for Spring Boot, is not the scope of this tutorial to dig into the Spring Boot details. That will be part of another tutorial πŸ™‚

 

Create Artifact’s  pom.xml 

Create a base directory called basic-spring-boot-archetype and file pom.xml. The contents of this file should be.

<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.darksideofthedev</groupId>
	<artifactId>dark-spring-boot-app</artifactId>
	<version>1.0-SNAPSHOT</version>
	<packaging>jar</packaging>

</project>

Here, <groupId> and <artifactId> will be the actual name of our archetype when we want to create new projects.

 

Create the archetype descriptor file.

Inside the folder you just created, you’ll need to create a folder structure like this src/main/resources/META-INF/maven. Inside /maven folder create a file archetype.xml and add the following code. The <id> should be the same as the <artifactId> from the artifact pom from before.

<archetype xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype/1.0.0 http://maven.apache.org/xsd/archetype-1.0.0.xsd">
	
	<id>dark-spring-boot-app</id>

	<sources>
		<source>src/main/java/DarkApp.java</source>
		<source>src/main/java/controller/DarkController.java</source>
		<source>src/main/java/service/DarkService.java</source>
	</sources>
	<resources>
		<resource>src/main/resources/application.properties</resource>
	</resources>
	<testSources>
		<source>src/test/java/controller/DarkControllerTest.java</source>
		<source>src/test/java/service/DarkServiceTest.java</source>
	</testSources>
	<testResources>
		<resource>src/test/resources/application.properties</resource>
	</testResources>

</archetype>

As you can see, our archetype will have 3 java classes (DarkApp.javaDarkController.java, and DarkService.java) along with its test classes and 2 properties files (one for the main sources and the other for tests).

 

Create the pom.xml file for the actual project.

Go back to src/main/resources/ folder and create a new folder archetype-resources and inside a pom.xml file. This file will contain the actual project structure with all its dependencies and configuration.

<?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>${groupId}</groupId>
	<artifactId>${artifactId}</artifactId>
	<version>${version}</version>
	<packaging>jar</packaging>

	<name>Dark Spring Boot Demo</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.8.RELEASE</version>
		<relativePath/>
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</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>

Be sure that <groupId> and <artifactId> are set to variables ${groupId} and ${artifactId}. These will be used when we generate the actual project using the archetype.

Add Java sources

You will need to create several folders from here to put the .java source files for the project. From here you’ll need to create all contents from /src folder. The overall structure that you should end up having is like this.

β”œβ”€β”€ basic-spring-boot-archetype
β”‚ β”œβ”€β”€ pom.xml
β”‚ └── src
β”‚     └── main
β”‚         └── resources
β”‚             β”œβ”€β”€ archetype-resources
β”‚             β”‚ β”œβ”€β”€ pom.xml
β”‚             β”‚ └── src
β”‚             β”‚     β”œβ”€β”€ main
β”‚             β”‚     β”‚ β”œβ”€β”€ java
β”‚             β”‚     β”‚ β”‚ β”œβ”€β”€ controller
β”‚             β”‚     β”‚ β”‚ β”‚ └── DarkController.java
β”‚             β”‚     β”‚ β”‚ β”œβ”€β”€ DarkApp.java
β”‚             β”‚     β”‚ β”‚ └── service
β”‚             β”‚     β”‚ β”‚     └── DarkService.java
β”‚             β”‚     β”‚ └── resources
β”‚             β”‚     β”‚     └── application.properties
β”‚             β”‚     └── test
β”‚             β”‚         β”œβ”€β”€ java
β”‚             β”‚         β”‚ β”œβ”€β”€ controller
β”‚             β”‚         β”‚ β”‚ └── DarkControllerTest.java
β”‚             β”‚         β”‚ └── service
β”‚             β”‚         β”‚     └── DarkServiceTest.java
β”‚             β”‚         └── resources
β”‚             β”‚             └── application.properties
β”‚             └── META-INF
β”‚                 └── maven
β”‚                     └── archetype.xml

 

Then create the following files according to that folder structure.

DarkApp.java

package ${package};

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

@SpringBootApplication
public class DarkApp {

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

DarkController.java

package ${package}.controller;

import ${package}.service.DarkService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DarkController {

    @Autowired
    private DarkService darkService;

    @GetMapping(&quot;hello&quot;)
    public String sayDarkHello(){

        return darkService.sayHelloDark();
    }
}

DarkService.java

package ${package}.service;

import org.springframework.stereotype.Service;

@Service
public class DarkService {


    public String sayHelloDark() {
        return &quot;Hello Dark World!!!&quot;;
    }
}

DarkControllerTest.java

package ${package}.controller;

import com.lightsideofthedev.service.DarkService;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import static org.junit.Assert.*;

public class DarkControllerTest {

    private final String TEST_RESPONSE = &quot;Hello World!!!&quot;;

    @InjectMocks
    private DarkController darkController;

    @Mock
    private DarkService darkService;

    @Before
    public void setUp(){
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void sayDarkHello() throws Exception {

        Mockito.when(darkService.sayHelloDark()).thenReturn(TEST_RESPONSE);

        String actualResponse = darkController.sayDarkHello();

        assertEquals(TEST_RESPONSE, actualResponse);
    }

}

DarkServiceTest.java

package ${package}.service;

import com.lightsideofthedev.service.DarkService;
import org.junit.Before;
import org.junit.Test;


import static org.junit.Assert.*;

public class DarkServiceTest {

	private final String TEST_RESPONSE = &quot;Hello Dark World!!!&quot;;

	private DarkService darkService;

	@Before
	public void setUp(){
		darkService = new DarkService();
	}

    @Test
    public void sayDarkHello() throws Exception {

    	assertEquals(TEST_RESPONSE, darkService.sayHelloDark());

    }

}

application.properties

server.port=8181

 

Building the archetype and creating a new project from it.

Now that you have all in place, run this command from the basic-spring-boot-archetype root folder in order to build the archetype and put it into your local maven repository.

mvn clean install

If everything goes well, you should have your archetype installed locally. Now is time to use it and generate our final Spring Boot project.

Move to another directory outside basic-spring-boot-archetype and run this command to create the actual project. For DgroupId and DartifactId you can put your own names but for this example, I’ll use com.lightsideofthedev and light-spring-boot-app.

mvn archetype:generate
	-DarchetypeGroupId=com.darksideofthedev		\
	-DarchetypeArtifactId=dark-spring-boot-app	\
	-DarchetypeVersion=1.0-SNAPSHOT				\
	-DgroupId=com.lightsideofthedev				\
	-DartifactId=light-spring-boot-app			\

 

This will create a folder light-spring-boot-app with the final project. Finally, open it with your favorite IDE and you should have a functional Spring Boot Application ready to be used.

Summary

You’ve learned about maven, what is used for and what are its benefits. You came to know what an archetype is, what is used for and how can we create one from scratch. From now you can play around to create any kind of project structure that will help you speed up thing a little bit when trying to build a project.


You can find the sources for this project in the link below.