In this tutorial, we will create two Spring Boot microservices, containerize them using Docker, and establish communication between them. Microservices allow you to develop and deploy applications as a collection of loosely coupled services. As a containerization platform, Docker simplifies the deployment and scaling of these services.
What You’ll Learn:
- How to create two microservices using Spring Boot:
product-service
andorder-service
. - How to containerize Spring Boot applications with Docker.
- How to enable inter-service communication using Feign Client.
This guide is designed for beginners and includes detailed steps and explanations to ensure you can easily follow along.
Introduction to Microservices and Docker
In modern software development, microservices architecture allows developers to break down large applications into smaller, manageable services. Each service is responsible for a specific functionality and communicates over standard protocols such as HTTP, making it easier to scale and maintain applications. Docker helps simplify this process by encapsulating each microservice into containers, ensuring consistent development, testing, and production environments.
Why Use Docker with Microservices?
Docker is a popular tool in the microservices world because:
- Simplified deployment: Containerization bundles everything your app needs (libraries, environment) into one package.
- Isolation: Each microservice runs in its own container, ensuring dependencies don't conflict.
- Scalability: Containers are lightweight and can be scaled independently.
Prerequisites
Before diving in, ensure that you have the following tools installed:
- JDK 17 or later
- Maven or Gradle (to build the project)
- Docker
- IDE (like IntelliJ IDEA or Eclipse)
Step 1: Create Two Spring Boot Projects
We will create two Spring Boot microservices:
- product-service: Provides product details.
- order-service: Manages orders and communicates with
product-service
to fetch product details.
Why Two Services?
By splitting the functionality into two microservices, we demonstrate inter-service communication and show how Docker containers can work together on a network.
Step 2: Set Up product-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
Set up your application.properties
file to define the application name and port.
server.port=8081
spring.application.name=product-service
Explanation:
server.port=8081
: Specifies the port forproduct-service
.spring.application.name=product-service
: Sets the name of the application.
2.3 Create the Product Model
Define a Product
class to represent product data.
package com.example.productservice;
public class Product {
private String id;
private String name;
private double price;
// Constructor, getters, and setters
public Product(String id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
Explanation:
- This class models a product with attributes like
id
,name
, andprice
.
2.4 Create a Controller
Create a REST controller to expose product-related endpoints.
package com.example.productservice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProductController {
@GetMapping("/products/{id}")
public Product getProduct(@PathVariable String id) {
return new Product(id, "Sample Product", 99.99);
}
}
Explanation:
@RestController
: Defines the class as a REST controller.@GetMapping("/products/{id}")
: Maps GET requests to this endpoint to return product 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/product-service-0.0.1-SNAPSHOT.jar product-service.jar
# Expose port 8081
EXPOSE 8081
# Run the application
ENTRYPOINT ["java", "-jar", "product-service.jar"]
Step 3: Set Up order-service
3.1 Create the Project
Go to Spring Initializr and create another Spring Boot project with these dependencies:
- Spring Web
- Spring Boot Actuator
- OpenFeign (for communication between microservices)
3.2 Configure application.properties
server.port=8082
spring.application.name=order-service
# URL of product-service
product.service.url=http://product-service:8081
Explanation:
product.service.url
: Defines the URL of theproduct-service
for communication in Docker.
3.3 Enable Feign Client
Add the @EnableFeignClients
annotation in the main application class:
package com.example.orderservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
3.4 Create a Feign Client Interface
Create a Feign client to call the product-service
:
package com.example.orderservice;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "product-service", url = "${product.service.url}")
public interface ProductServiceClient {
@GetMapping("/products/{id}")
Product getProductById(@PathVariable String id);
}
3.5 Create a Controller
Create a controller in order-service
to manage orders:
package com.example.orderservice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
private final ProductServiceClient productServiceClient;
public OrderController(ProductServiceClient productServiceClient) {
this.productServiceClient = productServiceClient;
}
@GetMapping("/orders/{productId}")
public String createOrder(@PathVariable String productId) {
Product product = productServiceClient.getProductById(productId);
return "Order created for product: " + product.getName() + " with price: $" + product.getPrice();
}
}
Step 4: Build Docker Images
Build the Docker images for both services.
For product-service
:
mvn clean package
docker build -t product-service .
For order-service
:
mvn clean package
docker build -t order-service .
Step 5: Create a Docker Network
Create a Docker network for the services to communicate:
docker network create microservices-net
Step 6: Run the Microservices
Run the containers:
docker run -d --net microservices-net --name product-service -p 8081:8081 product-service
docker run -d --net microservices-net --name order-service -p 8082:8082 order-service
Step 7: Test the Microservices
To test the setup, use Postman or your browser:
- product-service: http://localhost:8081/products/1
- order-service: http://localhost:8082/orders/1
Conclusion
You have successfully built two Spring Boot microservices, containerized them using Docker, and enabled inter-service communication via REST APIs and Feign clients. This setup can be further expanded by adding more services or implementing more advanced communication patterns. Docker allows for easy scalability and consistency across environments.
Next Steps:
- Add more microservices.
- Implement database connections and service discovery (e.g., using Spring Cloud).
Comments
Post a Comment