Spring Boot Microservices Eureka Server Example

In this tutorial, we'll create two Spring Boot microservices and register them with an Eureka server. We'll use the latest Spring Boot version 3.2+ and Spring Cloud 2023.x. This guide is intended for beginners and will include detailed explanations for each step.

Introduction to Eureka Server

Eureka Server is a service registry that allows microservices to register themselves and discover other registered services. This dynamic discovery mechanism helps in managing communication between services in a distributed system. With Eureka, microservices can automatically find each other, reducing the need for hardcoding service addresses and making the system more resilient and scalable.

Flow of the System

  1. Eureka Server: Acts as a central registry where microservices register themselves.
  2. Microservices: Register with Eureka Server and discover other registered services via Eureka.
  3. Service Discovery: Microservices query the Eureka Server to find the network locations of other microservices.

Prerequisites

  • JDK 17 or later
  • Maven or Gradle
  • IDE (IntelliJ IDEA, Eclipse, etc.)

Step 1: Set Up the 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

Explanation:

  • server.port=8761: Sets the port for the Eureka Server.
  • spring.application.name=eureka-server: Names the application.
  • eureka.client.register-with-eureka=false: Indicates that the Eureka Server itself should not try to register with another Eureka Server.
  • eureka.client.fetch-registry=false: Indicates that the Eureka Server should not attempt to fetch registry information from another Eureka Server.

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);
    }
}

Explanation:

  • @EnableEurekaServer: Enables the Eureka Server functionality in your Spring Boot application.

Step 2: Set Up product-service

2.1 Create the Project

Use Spring Initializr to create a new project with the following dependencies:

  • Spring Web
  • Eureka Discovery Client

2.2 Configure application.properties

Set up the application properties for product-service.

server.port=8081
spring.application.name=product-service

eureka.client.service-url.default-zone=http://localhost:8761/eureka/

Explanation:

  • server.port=8081: Sets the port for the Product Service.
  • spring.application.name=product-service: Names the application.
  • eureka.client.service-url.default-zone=http://localhost:8761/eureka/: Specifies the Eureka Server URL for service registration.

2.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);
    }
}

Explanation:

  • @EnableDiscoveryClient: Indicates that this application should register with a Eureka Server for service discovery.

2.4 Create a Product Model

Create a simple Product model to represent the 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 represents the product data with attributes id, name, and price.

2.5 Create a Controller

Create a controller to handle product-related requests.

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) {
        // In a real application, this data would come from a database
        return new Product(id, "Sample Product", 99.99);
    }
}

Explanation:

  • @RestController: Marks this class as a REST controller.
  • @GetMapping("/products/{id}"): Maps GET requests to /products/{id} to this method.
  • @PathVariable String id: Extracts the id from the URL.

Step 3: Set Up order-service

3.1 Create the Project

Use Spring Initializr to create a new project with the following dependencies:

  • Spring Web
  • Eureka Discovery Client
  • OpenFeign

3.2 Configure application.properties

Set up the application properties for order-service.

server.port=8082
spring.application.name=order-service

eureka.client.service-url.default-zone=http://localhost:8761/eureka/

Explanation:

  • server.port=8082: Sets the port for the Order Service.
  • spring.application.name=order-service: Names the application.
  • eureka.client.service-url.default-zone=http://localhost:8761/eureka/: Specifies the Eureka Server URL for service registration.

3.3 Enable Feign Clients and Eureka Client

Enable Feign clients and Eureka client functionality by adding the @EnableFeignClients and @EnableDiscoveryClient annotations 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;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

Explanation:

  • @EnableFeignClients: Enables Feign client functionality in your Spring Boot application.
  • @EnableDiscoveryClient: Indicates that this application should register with a Eureka Server for service discovery.

3.4 Create a 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 ProductServiceClient {

    @GetMapping("/products/{id}")
    Product getProductById(@PathVariable String id);
}

Explanation:

  • @FeignClient(name = "product-service"): Declares this interface as a Feign client for the product-service.
  • @GetMapping("/products/{id}"): Maps the GET request to the /products/{id} endpoint in product-service.

3.5 Create a Product Model

Create a Product model to match the one in product-service.

package com.example.orderservice;

public class Product {
    private String id;
    private String name;
    private double price;

    // Constructor, getters, and setters
    public Product() {}

    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 represents the product data with attributes id, name, and price.

3.6 Create a Controller

Create a controller to handle order-related requests and use the ProductServiceClient to fetch product details.

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();
    }
}

Explanation:

  • @RestController: Marks this class as a REST controller.
  • @GetMapping("/orders/{productId}"): Maps GET requests to /orders/{productId} to this method.
  • `ProductServiceClient productService

Client: Injects the Feign client for communication withproduct-service`.

Step 4: Run the Microservices

  1. Start the Eureka Server: Run the EurekaServerApplication class.
  2. Start product-service: Run the ProductServiceApplication class.
  3. Start order-service: Run the OrderServiceApplication class.

Step 5: Test the Communication

Open your browser or use a tool like Postman to test the endpoints:

  • product-service: http://localhost:8081/products/1
  • order-service: http://localhost:8082/orders/1

The response from order-service should include the product details fetched from product-service.

Conclusion

You have successfully set up two Spring Boot microservices and registered them with an Eureka Server. The Eureka Server acts as a service registry, enabling the microservices to discover and communicate with each other. This setup demonstrates how to use Spring Cloud components to create a scalable and maintainable microservices architecture. This setup can be expanded to include more microservices and more complex communication patterns.


Comments