- Product Service: Manages product information.
- Order Service: Manages customer orders.
- Inventory Service: Manages product inventory.
- Eureka Server: Service discovery.
- API Gateway: Acts as a single entry point to the system.
Prerequisites
- JDK 17 or later
- Maven or Gradle
- Docker
- Docker Compose
- IDE (IntelliJ IDEA, Eclipse, etc.)
Simple Microservices Architecture
Here is the simple microservices architecture for this e-commerce microservices application:
+-----------------------------+
| Postman Client |
| (Client for Testing) |
+-----------------------------+
|
v
+-----------------------------+ +-----------------------------+
| API Gateway | | Eureka Server |
| (Single Entry Point to the | ---------->| (Service Discovery) |
| System) | +-----------------------------+
+-----------------------------+
|
v
+----------------------+-----------------------+
| | |
v v v
+-----------------+ +-----------------+ +------------------+
| Product Service | | Order Service | | Inventory Service|
| (Manages | | (Manages Orders)| | (Manages |
| Product Info) | | | | Inventory) |
+-----------------+ +-----------------+ +------------------+
Explanation:
-
Postman Client: Used for testing the APIs. This client sends requests to the API Gateway.
-
API Gateway: The single entry point to the system, handling incoming requests and routing them to the appropriate microservice.
-
Eureka Server: This is the service discovery component where all microservices register themselves. It enables the discovery of services for communication.
-
Product Service: Manages product information such as details, pricing, and availability.
-
Order Service: Manages customer orders, processing new orders, updating order status, etc.
-
Inventory Service: Manages product inventory, keeping track of stock levels and updating inventory records.
The Postman client sends requests to the API Gateway, which uses the Eureka Server to locate the appropriate microservice. Each microservice registers itself with the Eureka Server and communicates with other microservices as needed.
Step 1: Set Up Eureka Server
1.1 Create the Project
Use Spring Initializr to create a new project with the following dependencies:
- Eureka Server
1.2 Configure application.properties
Set up the application properties for the Eureka Server.
server.port=8761
spring.application.name=eureka-server
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
1.3 Enable Eureka Server
Add the @EnableEurekaServer
annotation to the main application class.
package com.example.eurekaserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
Step 2: Set Up API Gateway
2.1 Create the Project
Use Spring Initializr to create a new project with the following dependencies:
- Spring Cloud Gateway
- Eureka Discovery Client
2.2 Configure application.properties
Set up the application properties for the API Gateway.
server.port=8080
spring.application.name=api-gateway
eureka.client.service-url.default-zone=http://localhost:8761/eureka/
spring.cloud.gateway.discovery.locator.enabled=true
spring.cloud.gateway.discovery.locator.lower-case-service-id=true
2.3 Enable Eureka Client and Gateway
Add the @EnableDiscoveryClient
annotation in the main application class.
package com.example.apigateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
}
Step 3: Set Up Product Service
3.1 Create the Project
Use Spring Initializr to create a new project with the following dependencies:
- Spring Web
- Spring Boot Actuator
- Spring Data JPA
- H2 Database
- Eureka Discovery Client
3.2 Configure application.properties
Set up the application properties for the Product Service.
server.port=8081
spring.application.name=product-service
eureka.client.service-url.default-zone=http://localhost:8761/eureka/
spring.datasource.url=jdbc:h2:mem:productdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.h2.console.enabled=true
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
3.3 Enable Eureka Client
Add the @EnableDiscoveryClient
annotation to the main application class.
package com.example.productservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
3.4 Create Product Model
Create a simple Product model.
package com.example.productservice;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Product {
@Id
private String id;
private String name;
private double price;
// Getters and setters
}
3.5 Create Product Repository
Create a repository interface to manage Product entities.
package com.example.productservice;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ProductRepository extends JpaRepository<Product, String> {
}
3.6 Create Product Service
Create a service to handle product-related business logic.
package com.example.productservice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
public List<Product> getAllProducts() {
return productRepository.findAll();
}
public Product getProductById(String id) {
return productRepository.findById(id).orElse(null);
}
public Product addProduct(Product product) {
return productRepository.save(product);
}
}
3.7 Create Product Controller
Create a controller to handle HTTP requests.
package com.example.productservice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/products")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping
public List<Product> getAllProducts() {
return productService.getAllProducts();
}
@GetMapping("/{id}")
public Product getProductById(@PathVariable String id) {
return productService.getProductById(id);
}
@PostMapping
public Product addProduct(@RequestBody Product product) {
return productService.addProduct(product);
}
}
Step 4: Set Up Order Service
4.1 Create the Project
Use Spring Initializr to create a new project with the following dependencies:
- Spring Web
- Spring Boot Actuator
- Spring Data JPA
- H2 Database
- Eureka Discovery Client
- OpenFeign
4.2 Configure application.properties
Set up the application properties for the Order Service.
server.port=8082
spring.application.name=order-service
eureka.client.service-url.default-zone=http://localhost:8761/eureka/
spring.datasource.url=jdbc:h2:mem:orderdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.h2.console.enabled=true
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
4.3 Enable Eureka Client and Feign Clients
Add the @EnableDiscoveryClient
and @EnableFeignClients
annotations to the main application class.
package com.example.orderservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
4.4 Create Order Model
Create a simple Order model.
package com.example.orderservice;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Order {
@Id
private String id;
private String productId;
private int quantity;
// Getters and setters
}
4.5 Create Order Repository
Create a repository interface to manage Order entities.
package com.example.orderservice;
import org.springframework.data.jpa.repository.JpaRepository;
public interface OrderRepository extends JpaRepository<Order, String> {
}
4.6 Create Product Client
Create a Feign client interface to communicate with 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")
public interface ProductClient {
@GetMapping("/products/{id}")
Product getProductById(@PathVariable String id);
}
4.7 Create Product DTO
Create a Product DTO to match the one in product-service
.
package com.example.orderservice;
public class Product {
private String id;
private String name;
private double price;
// Getters and setters
}
4.8 Create Order Service
Create a service to handle order-related business logic.
package com.example.orderservice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private ProductClient productClient;
public List<Order> getAllOrders() {
return orderRepository.findAll();
}
public Order getOrderById(String id) {
return orderRepository.findById(id).orElse(null);
}
public Order addOrder(Order order) {
Product product = productClient.getProductById(order.getProductId());
if (product != null) {
return orderRepository.save(order);
} else {
throw new RuntimeException("Product not found");
}
}
}
4.9 Create Order Controller
Create a controller to handle HTTP requests.
package com.example.orderservice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Rest
Controller
@RequestMapping("/orders")
public class OrderController {
@Autowired
private OrderService orderService;
@GetMapping
public List<Order> getAllOrders() {
return orderService.getAllOrders();
}
@GetMapping("/{id}")
public Order getOrderById(@PathVariable String id) {
return orderService.getOrderById(id);
}
@PostMapping
public Order addOrder(@RequestBody Order order) {
return orderService.addOrder(order);
}
}
Step 5: Set Up Inventory Service
5.1 Create the Project
Use Spring Initializr to create a new project with the following dependencies:
- Spring Web
- Spring Boot Actuator
- Spring Data JPA
- H2 Database
- Eureka Discovery Client
5.2 Configure application.properties
Set up the application properties for the Inventory Service.
server.port=8083
spring.application.name=inventory-service
eureka.client.service-url.default-zone=http://localhost:8761/eureka/
spring.datasource.url=jdbc:h2:mem:inventorydb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.h2.console.enabled=true
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
5.3 Enable Eureka Client
Add the @EnableDiscoveryClient
annotation to the main application class.
package com.example.inventoryservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class InventoryServiceApplication {
public static void main(String[] args) {
SpringApplication.run(InventoryServiceApplication.class, args);
}
}
5.4 Create Inventory Model
Create a simple Inventory model.
package com.example.inventoryservice;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Inventory {
@Id
private String productId;
private int quantity;
// Getters and setters
}
5.5 Create Inventory Repository
Create a repository interface to manage Inventory entities.
package com.example.inventoryservice;
import org.springframework.data.jpa.repository.JpaRepository;
public interface InventoryRepository extends JpaRepository<Inventory, String> {
}
5.6 Create Inventory Service
Create a service to handle inventory-related business logic.
package com.example.inventoryservice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class InventoryService {
@Autowired
private InventoryRepository inventoryRepository;
public List<Inventory> getAllInventory() {
return inventoryRepository.findAll();
}
public Inventory getInventoryByProductId(String productId) {
return inventoryRepository.findById(productId).orElse(null);
}
public Inventory updateInventory(String productId, int quantity) {
Inventory inventory = inventoryRepository.findById(productId).orElseThrow(() -> new RuntimeException("Product not found"));
inventory.setQuantity(quantity);
return inventoryRepository.save(inventory);
}
}
5.7 Create Inventory Controller
Create a controller to handle HTTP requests.
package com.example.inventoryservice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/inventory")
public class InventoryController {
@Autowired
private InventoryService inventoryService;
@GetMapping
public List<Inventory> getAllInventory() {
return inventoryService.getAllInventory();
}
@GetMapping("/{productId}")
public Inventory getInventoryByProductId(@PathVariable String productId) {
return inventoryService.getInventoryByProductId(productId);
}
@PutMapping("/{productId}")
public Inventory updateInventory(@PathVariable String productId, @RequestParam int quantity) {
return inventoryService.updateInventory(productId, quantity);
}
}
Step 6: Run the Services
- Start the Eureka Server: Run the
EurekaServerApplication
class. - Start the API Gateway: Run the
ApiGatewayApplication
class. - Start the Product Service: Run the
ProductServiceApplication
class. - Start the Order Service: Run the
OrderServiceApplication
class. - Start the Inventory Service: Run the
InventoryServiceApplication
class.
Step 7: Test the E-Commerce Application
-
Test the Product Service:
- Add products using
POST /products
:{ "id": "1", "name": "Product 1", "price": 100.0 }
- Retrieve products using
GET /products
.
- Add products using
-
Test the Order Service:
- Create orders using
POST /orders
:{ "id": "1", "productId": "1", "quantity": 1 }
- Retrieve orders using
GET /orders
.
- Create orders using
-
Test the Inventory Service:
- Update inventory using
PUT /inventory/{productId}?quantity=10
. - Retrieve inventory using
GET /inventory
.
- Update inventory using
Conclusion
You have successfully set up a basic e-commerce application using Spring Boot microservices architecture. This setup includes a Product Service, Order Service, Inventory Service, Eureka Server for service discovery, and an API Gateway. This example can be expanded with more features such as user management, payment processing, and more complex business logic.
Comments
Post a Comment