Lab: Spring Cloud Microservices - Eureka & Feign
Lab Overview
In this lab, you will build a simple microservices architecture consisting of:
- A Eureka Server for service discovery
- Two microservices that communicate with each other using Feign
The scenario will be a basic e-commerce system with:
- Product Service: manages product information
- Order Service: creates orders and fetches product details from the Product Service
Let’s break this down into clear, manageable steps.
Lab Instructions
Prerequisites
- Java 17 or higher
- Maven or Gradle
- IDE (IntelliJ IDEA, Eclipse, or VS Code)
- Basic knowledge of Spring Boot
Step 1: Set up the Eureka Server
- Create a new Spring Boot project at Spring Initializer with the following:
- Artifact: eureka-server
- Dependencies: Eureka Server
- Open the main application class and add
@EnableEurekaServer
:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
- Configure the server in
application.properties
:
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
spring.application.name=eureka-server
- Run the application and visit http://localhost:8761 to see the Eureka dashboard.
Step 2: Create the Product Service
- Create a new Spring Boot project with:
- Artifact: product-service
- Dependencies: Spring Web, Eureka Discovery Client
- Configure the application in
application.properties
:
spring.application.name=product-service
server.port=8081
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
- Create a Product model class:
public class Product {
private Long id;
private String name;
private String description;
private double price;
// Constructor, getters, setters
}
- Create a ProductController:
@RestController
@RequestMapping("/products")
public class ProductController {
private Map<Long, Product> productMap = new HashMap<>();
@PostConstruct
public void setupProducts() {
Product p1 = new Product(1L, "Laptop", "High performance laptop", 999.99);
Product p2 = new Product(2L, "Phone", "Smartphone with great camera", 699.99);
productMap.put(p1.getId(), p1);
productMap.put(p2.getId(), p2);
}
@GetMapping
public List<Product> getAllProducts() {
return new ArrayList<>(productMap.values());
}
@GetMapping("/{id}")
public Product getProduct(@PathVariable Long id) {
return productMap.get(id);
}
}
- Enable Eureka client in the main application class:
@SpringBootApplication
@EnableEurekaClient
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
Step 3: Create the Order Service
- Create a new Spring Boot project with:
- Artifact: order-service
- Dependencies: Spring Web, Eureka Discovery Client, OpenFeign
- Configure the application in
application.properties
:
spring.application.name=order-service
server.port=8082
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
- Enable Eureka client and Feign clients in the main application class:
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
-
Create a Product model class (identical to the one in Product Service).
-
Create an Order model class:
public class Order {
private Long id;
private Long productId;
private int quantity;
private double totalPrice;
private Product product;
// Constructor, getters, setters
}
- Create a Feign client to communicate with the Product Service:
@FeignClient(name = "product-service")
public interface ProductClient {
@GetMapping("/products/{id}")
Product getProduct(@PathVariable("id") Long id);
}
- Create an OrderController:
@RestController
@RequestMapping("/orders")
public class OrderController {
private final ProductClient productClient;
private final Map<Long, Order> orderMap = new HashMap<>();
private Long nextOrderId = 1L;
public OrderController(ProductClient productClient) {
this.productClient = productClient;
}
@PostMapping
public Order createOrder(@RequestBody Order order) {
// Get product details from product-service
Product product = productClient.getProduct(order.getProductId());
// Set order details
order.setId(nextOrderId++);
order.setProduct(product);
order.setTotalPrice(product.getPrice() * order.getQuantity());
// Save order
orderMap.put(order.getId(), order);
return order;
}
@GetMapping("/{id}")
public Order getOrder(@PathVariable Long id) {
return orderMap.get(id);
}
@GetMapping
public List<Order> getAllOrders() {
return new ArrayList<>(orderMap.values());
}
}
Step 4: Test the Microservices
- Start all three applications in this order:
- Eureka Server
- Product Service
- Order Service
-
Check the Eureka dashboard at http://localhost:8761 to confirm both services are registered.
-
Test the Product Service:
- GET http://localhost:8081/products
- GET http://localhost:8081/products/1
- Test the Order Service by creating a new order:
-
POST http://localhost:8082/orders
{ "productId": 1, "quantity": 2 }
-
GET http://localhost:8082/orders
Lab Assignments
-
Basic: Add another endpoint in the Product Service and access it from the Order Service.
-
Intermediate: Add a third microservice (e.g., User Service) and integrate it with the existing services.
-
Advanced: Implement circuit breaking with Resilience4j or Hystrix to handle failures gracefully.
Discussion Questions
- How does service discovery with Eureka simplify microservice architecture?
- What are the advantages of using Feign over RestTemplate?
- How would you handle a situation where the Product Service is down?
- What are some potential scaling challenges in this architecture?
Key Concepts to Highlight
- Service Discovery: Allows services to find and communicate with each other without hardcoding hostnames and ports
- Client-Side Load Balancing: Provided by Ribbon (integrated with Feign)
- Declarative REST Client: Feign simplifies API calls between services
- Microservice Communication: Synchronous communication patterns
This lab provides hands-on experience with core Spring Cloud components while demonstrating practical microservice patterns.
By Wahid Hamdi