In this tutorial, we will create two Spring Boot microservices, containerize them using Docker, and establish communication between them. The microservices will handle employee and department data, and Docker will help us deploy these services in isolated containers.
What You’ll Learn:
- How to create two microservices using Spring Boot:
employee-service
anddepartment-service
. - How to containerize Spring Boot applications using Docker.
- How to enable inter-service communication using Feign Client.
This guide is designed for beginners and includes detailed explanations for each step.
Introduction to Microservices and Docker
In a microservices architecture, an application is split into multiple smaller services, each responsible for a specific feature. Each service can be developed, deployed, and scaled independently. Docker simplifies the deployment process by allowing developers to package these microservices into containers.
Prerequisites
Before starting, ensure you have the following tools installed:
- JDK 17 or later
- Maven or Gradle
- Docker
- IDE (like IntelliJ IDEA or Eclipse)
Step 1: Create Two Spring Boot Projects
We will create two Spring Boot microservices:
- employee-service: Manages employee details.
- department-service: Manages department details and communicates with
employee-service
to fetch employee information.
Why Two Services?
This example demonstrates how microservices communicate with each other using REST APIs, with each service containerized and running independently.
Step 2: Set Up employee-service
2.1 Create the Project
Go to Spring Initializr and create a new Spring Boot project with the following dependencies:
- Spring Web
- Spring Boot Actuator
2.2 Configure application.properties
Configure the application properties for employee-service
.
server.port=8081
spring.application.name=employee-service
Explanation:
server.port=8081
: Sets the port foremployee-service
.spring.application.name=employee-service
: Defines the name of the service.
2.3 Create the Employee Model
Create an Employee
class to represent employee data.
package com.example.employeeservice;
public class Employee {
private String id;
private String name;
private String department;
// Constructor, getters, and setters
public Employee(String id, String name, String department) {
this.id = id;
this.name = name;
this.department = department;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getDepartment() {
return department;
}
}
Explanation:
- This class models an employee with attributes like
id
,name
, anddepartment
.
2.4 Create a Controller
Create a REST controller to expose employee-related endpoints.
package com.example.employeeservice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EmployeeController {
@GetMapping("/employees/{id}")
public Employee getEmployee(@PathVariable String id) {
return new Employee(id, "John Doe", "Engineering");
}
}
Explanation:
@RestController
: Defines the class as a REST controller.@GetMapping("/employees/{id}")
: Maps GET requests to return employee details.
2.5 Create a Dockerfile
Create a Dockerfile
in the root directory of the project:
# Use an official JDK runtime as a parent image
FROM openjdk:17-jdk-alpine
# Set the working directory in the container
WORKDIR /app
# Copy the JAR file into the container
COPY target/employee-service-0.0.1-SNAPSHOT.jar employee-service.jar
# Expose port 8081
EXPOSE 8081
# Run the application
ENTRYPOINT ["java", "-jar", "employee-service.jar"]
Step 3: Set Up department-service
3.1 Create the Project
Go to Spring Initializr and create a new Spring Boot project with the following dependencies:
- Spring Web
- Spring Boot Actuator
- OpenFeign (for inter-service communication)
3.2 Configure application.properties
Set up the application properties for department-service
.
server.port=8082
spring.application.name=department-service
# URL of employee-service
employee.service.url=http://employee-service:8081
Explanation:
employee.service.url
: Specifies the URL for theemployee-service
to enable communication between services.
3.3 Enable Feign Client
Add the @EnableFeignClients
annotation in the main application class:
package com.example.departmentservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class DepartmentServiceApplication {
public static void main(String[] args) {
SpringApplication.run(DepartmentServiceApplication.class, args);
}
}
3.4 Create a Feign Client Interface
Define a Feign client to communicate with the employee-service
:
package com.example.departmentservice;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "employee-service", url = "${employee.service.url}")
public interface EmployeeServiceClient {
@GetMapping("/employees/{id}")
Employee getEmployeeById(@PathVariable String id);
}
3.5 Create the Employee Model
Create an Employee
class in department-service
that matches the structure in employee-service
:
package com.example.departmentservice;
public class Employee {
private String id;
private String name;
private String department;
// Constructor, getters, and setters
public Employee() {}
public Employee(String id, String name, String department) {
this.id = id;
this.name = name;
this.department = department;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getDepartment() {
return department;
}
}
3.6 Create a Controller
Create a controller in department-service
to handle department-related requests and fetch employee details.
package com.example.departmentservice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DepartmentController {
private final EmployeeServiceClient employeeServiceClient;
public DepartmentController(EmployeeServiceClient employeeServiceClient) {
this.employeeServiceClient = employeeServiceClient;
}
@GetMapping("/departments/{employeeId}")
public String getEmployeeDepartment(@PathVariable String employeeId) {
Employee employee = employeeServiceClient.getEmployeeById(employeeId);
return "Employee " + employee.getName() + " works in the " + employee.getDepartment() + " department.";
}
}
3.7 Create a Dockerfile for department-service
Create a Dockerfile
in the root directory of the department-service
project:
# Use an official JDK runtime as a parent image
FROM openjdk:17-jdk-alpine
# Set the working directory in the container
WORKDIR /app
# Copy the JAR file into the container
COPY target/department-service-0.0.1-SNAPSHOT.jar department-service.jar
# Expose port 8082
EXPOSE 8082
# Run the application
ENTRYPOINT ["java", "-jar", "department-service.jar"]
Explanation:
- FROM openjdk:17-jdk-alpine: Uses an official JDK 17 image.
- WORKDIR /app: Sets the working directory within the container.
- COPY target/department-service-0.0.1-SNAPSHOT.jar department-service.jar: Copies the generated JAR file into the container.
- EXPOSE 8082: Exposes port 8082 for the
department-service
. - ENTRYPOINT: Specifies the command to start the application when the container starts.
Step 4: Build Docker Images
Build Docker images for both services.
For employee-service
:
mvn clean package
docker build -t employee-service .
For department-service
:
mvn clean package
docker build -t department-service .
Step 5: Create a Docker Network
Create a Docker network so the containers can communicate with each other:
docker network create microservices-net
Step 6: Run the Microservices
Run the Docker containers:
docker run -d --net microservices-net --name employee-service -p 8081:8081 employee-service
docker run -d --net microservices-net --name department-service -p 8082:8082 department-service
Step 7: Test the Microservices
Test the services using a browser or Postman.
- employee-service: http://localhost:8081/employees/1
- department-service: http://localhost:8082/departments/1
You should see a response from department-service
that includes employee details retrieved from employee-service
.
Conclusion
You have successfully created two Spring Boot microservices (employee-service
and department-service
), containerized them with Docker, and enabled communication between them using Feign clients. This architecture can be scaled to include more services or more advanced features like service discovery, load balancing, or database integration.
Next Steps:
- Add databases to both services (e.g., MySQL, PostgreSQL).
- Implement service discovery using Spring Cloud Netflix Eureka.
Comments
Post a Comment
Leave Comment