Build a microservices system with Java
Tags: java, microservices, tutorial, programming
Published: 2022-02-05 11:47:12


**Github repo for this project: (Please give me a Github star :star: for this effort! Thank you!)**
https://github.com/linhtch90/microservices-java-demo-zoo-devto


## Introduction

Microservice is the concept of decomposing a large monolith application into small, independent, distributed services. This could improve the flexibility, scalability and resiliency of the whole system.

The introduction of Spring Cloud framework makes it easier for developers to build and deploy microservices to private and public clouds. This framework has wrapped a wide varieties of popular cloud-management microservices frameworks under a well-organized framework.

In this blog post, I want to help you have an overview about Spring Cloud framework by building a simple microservices system with Spring Cloud step by step. This system includes the following components:

- Configuration server
- Service discovery with Eureka
- 2 demo microservices called Tiger and Panther
- Gateway server
- RabbitMQ for messaging between microservices

The relationships between those services are described as the following figure.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rtj39d2b1x7gnhuvr6op.png)

Let's begin building this system!

## Configuration server

Go to `start.spring.io` and generate a new project with the following information:

- Group ID: com.microservices.zooconfsvr
- Artifact ID: microservice-zoo-config-server
- Name: microservice-zoo-config-server
- Description: zoo microservices config server
- JDK: I am using JDK 17 for this tutorial. I have not tested this project with older JDKs yet!
- Dependencies: Config Server (So other services can get their configuration information from this service)

Your `pom.xml` should look like this:

```xml
<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-bootstrap</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-server</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
```

- In folder `src/main/resources/`, add a file called `bootstrap.properties` 
- In folder `src/main/resources/`, add a folder called `config/` and create 4 configuration files `eureka-server.properties`, `gateway-server.properties`, `panther-service.properties`, `tiger-service.properties`
- The content of those `.properties` files could be found in my Github repo I put the link on top of this blog post)

Add `@EnableConfigServer` annotation to the main entrance class `MicroserviceZooConfigServerApplication.java`.

## Service discovery (with Eureka)

Go to `start.spring.io` and generate a new project with the following information:

- Group ID: com.microservices.zooeurekasvr
- Artifact ID: microservice-zoo-services-discovery
- Name: microservice-zoo-services-discovery
- Description: zoo microservices services discovery
- Dependencies: Eureka server, config client

Your `pom.xml` should look like this:

```xml
<properties>
		<java.version>17</java.version>
		<spring-cloud.version>2021.0.0</spring-cloud.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-bootstrap</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-loadbalancer</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
```

- In folder `src/main/resources/`, add a file called `bootstrap.properties` 
- The content of those `.properties` files could be found in my Github repo (I put the link on top of this blog post)

Add `@EnableEurekaServer` annotation to `MicroserviceZooServicesDiscoveryApplication.java`

### Gateway server

Gateway server is the service that handles all request from client. Go to `start.spring.io` and generate a new project with the following information:

- Group ID: com.microservices.zoogateway
- Artifact ID: microservice-zoo-gateway
- Name: microservice-zoo-gateway
- Description: microservice gateway for the zoo demo
- Dependencies: Eureka client, config client, gateway

Your `pom.xml` should look like this:

```xml
<properties>
		<java.version>17</java.version>
		<spring-cloud.version>2021.0.0</spring-cloud.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-bootstrap</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-gateway</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
```

- In folder `src/main/resources/`, add a file called `bootstrap.properties` 
- The content of those `.properties` files could be found in my Github repo (I put the link on top of this blog post)

Add `@EnableEurekaServer` annotation to `MicroserviceZooGatewayApplication.java`

### Tiger service

Go to `start.spring.io` and generate a new project with the following information:

- Group ID: com.microservices.tigerservice
- Artifact ID: microservice-tiger
- Name: microservice-tiger
- Description: microservice tiger
- Dependencies: Eureka client, config client, web, client load balancer, open feign (also for load balancer), RabbitMQ

Your `pom.xml` should look like this:

```xml
<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-bootstrap</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-loadbalancer</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-openfeign</artifactId>
			<version>3.1.0</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
```

- In folder `src/main/resources/`, add a file called `bootstrap.properties` 
- The content of those `.properties` files could be found in my Github repo (I put the link on top of this blog post)

Add `@EnableFeignClients` annotation to `MicroserviceTigerApplication.java`

- Create `com.microservices.tigerservice.service` package and add 2 files `ClientToPantherService.java` for directly call Panther service and `RabitMQSender.java` for sending a string message to Panther via RabbitMQ. 
- Create `com.microservices.tigerservice.controller` package and add `TigerController.java`, specifying controllers for calling Panther service.
- Create `com.microservices.tigerservice.component` package and add `RabitMQSenderComponent.java` for creating Beans related to messaging service.
- Please refer to my Github repo for the content of these files.

## Panther service

Go to `start.spring.io` and generate a new project with the following information:

- Group ID: com.microservices.pantherservice
- Artifact ID: microservice-panther
- Name: microservice-panther
- Description: microservice panther
- Dependencies: Eureka client, config client, web, client load balancer, RabbitMQ

Your `pom.xml` should look like this:

```xml
<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-bootstrap</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-loadbalancer</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
```

- In folder `src/main/resources/`, add a file called `bootstrap.properties` 
- The content of those `.properties` files could be found in my Github repo (I put the link on top of this blog post)

Create controller and other components for the services as follow.

- Create `com.microservices.pantherservice.controller` package and add `TigerCallPanther.java` for directly respond to calls from Tiger service in the form of a string.
- Create `com.microservices.pantherservice.component` package and add 2 files `RabbitMQComponent.java` and `RabbitMQReceiver.java` for settings related to listening and responding to messages sent from Tiger service. Right after receiving the message from Tiger service, Panther service print the message into the Log.
- Please refer to my Github repo for the content of these files. 

## RabbitMQ

Please refer to [this tutorial](https://medium.com/m/global-identity?redirectUrl=https%3A%2F%2Fcodeburst.io%2Fget-started-with-rabbitmq-on-docker-4428d7f6e46b) for using RabbitMQ with Docker.

## Running the whole system

Please follow this order:

- Start RabbitMQ with Docker (see above section)
- Start Configuration server 
- Start Discovery service 
- Start Tiger service 
- Start Panther service 
- Start Gateway server

## Testing microservices with Postman

- Direct call from Tiger service to Panther service: Open Postman and send a request to 
 
```
http://localhost:8074/tiger-service/tiger/callpantherservice
```

The result should look like the following figure.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/daoh9nwggg4x9420aisd.png)


- Send message from Tiger service to Panther service: Open Postman and send a request to

```
http://localhost:8074/tiger-service/tiger/sendmessagetopanther
```

There is not any response in Postman. It is okay. Please go to the terminal screen where you are running Panther service. You will see a log message saying:

```Received message is: Message from Tiger to Panther via RabbitMQ```

**And that is all everybody!**

If you feel this project is useful for you, please give my project a Github star :star: as an encouragement!

Thank you so much!