Microservices

Building Microservices Using Spring Boot and Spring Cloud

By Utility Zone · 2025-11-04T15:23:06.447725

Building microservices with Spring Boot and Spring Cloud involves creating independent, loosely coupled services that work together to form a complete application. Spring Boot simplifies the development of individual microservices, while Spring Cloud provides tools to address distributed system challenges such as service discovery, configuration management, API gateways, and resilience patterns.123

Here's a comprehensive guide to building microservices using these technologies.


Architecture Overview

A typical Spring Boot microservices architecture consists of several key components:451

Core Microservices: Independent Spring Boot applications, each with its own database and business logic (e.g., Employee Service, Department Service, Organization Service).1

Service Registry (Eureka Server): Maintains a registry of all available microservices and their locations, enabling dynamic service discovery.56

API Gateway (Spring Cloud Gateway): Acts as a single entry point for all client requests, handling routing, load balancing, security, and cross-cutting concerns.75

Config Server: Centralizes configuration management across all microservices, allowing external configuration without code changes.85

Circuit Breaker (Resilience4j): Prevents cascading failures by monitoring service calls and providing fallback mechanisms when services fail.910


Step-by-Step Implementation

1. Setting Up Service Registry with Netflix Eureka

The Service Registry is the foundation of microservices communication, allowing services to discover each other dynamically.611

Create Eureka Server:

Start by creating a new Spring Boot project using Spring Initializr with the following configuration:6

  • Project: Maven
  • Language: Java
  • Packaging: Jar
  • Java: 17
  • Dependencies: Eureka Server

Add Dependencies (pom.xml):

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

Enable Eureka Server:

Annotate your main application class with @EnableEurekaServer:6

package com.example.discoveryservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

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

Configure application.properties:

server.port=8761
spring.application.name=discovery-service
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

The properties eureka.client.register-with-eureka=false and eureka.client.fetch-registry=false tell the Eureka server not to register itself as a client.6

Run the application and access the Eureka dashboard at http://localhost:8761/.6

2. Creating Microservices as Eureka Clients

Now create individual microservices that register themselves with the Eureka Server.121

Create a Spring Boot Microservice:

Use Spring Initializr with these dependencies:12

  • Spring Web
  • Spring Data JPA
  • MySQL Driver (or your preferred database)
  • Eureka Discovery Client
  • Spring Boot DevTools

Add Eureka Client Dependency (pom.xml):

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

Enable Eureka Client:

Annotate your main class with @EnableDiscoveryClient or simply rely on auto-configuration (Spring Boot 2.0+):

package com.example.employeeservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

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

Configure application.properties:

spring.application.name=employee-service
server.port=8081
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

The spring.application.name is crucial as it identifies the service in the Eureka registry.1

Create REST Controller:

@RestController
@RequestMapping("/api/employees")
public class EmployeeController {
    
    @Autowired
    private EmployeeService employeeService;
    
    @GetMapping("/{id}")
    public ResponseEntity<Employee> getEmployee(@PathVariable Long id) {
        Employee employee = employeeService.findById(id);
        return ResponseEntity.ok(employee);
    }
    
    @PostMapping
    public ResponseEntity<Employee> createEmployee(@RequestBody Employee employee) {
        Employee savedEmployee = employeeService.save(employee);
        return ResponseEntity.status(HttpStatus.CREATED).body(savedEmployee);
    }
}

Repeat this process to create additional microservices (e.g., Department Service, Organization Service). Each microservice should register with Eureka and operate on different ports.41

3. Inter-Service Communication

Microservices need to communicate with each other. Spring Cloud offers several approaches:13141

Using RestTemplate (Legacy, Synchronous):

@Configuration
public class RestTemplateConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

@Service
public class EmployeeService {
    @Autowired
    private RestTemplate restTemplate;
    
    public Department getDepartment(Long deptId) {
        return restTemplate.getForObject(
            "http://department-service/api/departments/" + deptId, 
            Department.class
        );
    }
}

The @LoadBalanced annotation enables client-side load balancing through Ribbon.1

Using WebClient (Modern, Reactive):

@Service
public class EmployeeService {
    private final WebClient webClient;
    
    public EmployeeService(WebClient.Builder webClientBuilder) {
        this.webClient = webClientBuilder.baseUrl("http://department-service").build();
    }
    
    public Mono<Department> getDepartment(Long deptId) {
        return webClient.get()
            .uri("/api/departments/{id}", deptId)
            .retrieve()
            .bodyToMono(Department.class);
    }
}

Using Spring Cloud OpenFeign (Declarative):

Add dependency:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

Enable Feign clients and create an interface:1

@SpringBootApplication
@EnableFeignClients
public class EmployeeServiceApplication {
    // main method
}

@FeignClient(name = "department-service")
public interface DepartmentClient {
    @GetMapping("/api/departments/{id}")
    Department getDepartmentById(@PathVariable("id") Long departmentId);
}

@Service
public class EmployeeService {
    @Autowired
    private DepartmentClient departmentClient;
    
    public Department getDepartment(Long deptId) {
        return departmentClient.getDepartmentById(deptId);
    }
}

Feign provides cleaner syntax and built-in load balancing.14

4. Implementing API Gateway with Spring Cloud Gateway

The API Gateway serves as a single entry point for all microservices.1557

Create Gateway Project:

Use Spring Initializr with dependencies:715

  • Gateway
  • Eureka Discovery Client

Add Dependencies (pom.xml):

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

Configure Routes (application.yml):

server:
  port: 8080

spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
      routes:
        - id: employee-service
          uri: lb://employee-service
          predicates:
            - Path=/api/employees/**
          filters:
            - AddRequestHeader=X-Request-Gateway, ApiGateway
            
        - id: department-service
          uri: lb://department-service
          predicates:
            - Path=/api/departments/**

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

The lb:// prefix enables load balancing through the service registry. Predicates determine when a route matches, and filters modify requests/responses.157

Custom Filters (optional):

@Component
public class CustomGatewayFilter implements GlobalFilter, Ordered {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // Pre-processing
        ServerHttpRequest request = exchange.getRequest();
        System.out.println("Request Path: " + request.getPath());
        
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            // Post-processing
            ServerHttpResponse response = exchange.getResponse();
            System.out.println("Response Status: " + response.getStatusCode());
        }));
    }
    
    @Override
    public int getOrder() {
        return -1;
    }
}

5. Centralized Configuration with Spring Cloud Config Server

Externalizing configuration allows you to manage properties across all microservices from a central location.16178

Create Config Server:

Use Spring Initializr with Config Server dependency.8

Add Dependencies (pom.xml):

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>

Enable Config Server:

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

Configure application.properties:

spring.application.name=config-server
server.port=8888
spring.cloud.config.server.git.uri=file:///path/to/config-repo
# Or use a remote Git repository:
# spring.cloud.config.server.git.uri=https://github.com/username/config-repo

Create Configuration Files:

In your Git repository, create configuration files named after your microservices:8

  • employee-service.properties
  • department-service.properties

Example employee-service.properties:

server.port=8081
spring.datasource.url=jdbc:mysql://localhost:3306/employee_db
spring.datasource.username=root
spring.datasource.password=password

Commit and push these files to the repository.8

Configure Microservices as Config Clients:

Add dependency to your microservices:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

In application.properties:

spring.application.name=employee-service
spring.config.import=configserver:http://localhost:8888
spring.profiles.active=dev

Now your microservices will fetch configuration from the Config Server at startup.1716

6. Implementing Circuit Breaker with Resilience4j

Circuit breakers prevent cascading failures when downstream services fail.109

Add Resilience4j Dependency:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Configure Resilience4j (application.yml):

resilience4j:
  circuitbreaker:
    instances:
      departmentService:
        register-health-indicator: true
        sliding-window-size: 10
        minimum-number-of-calls: 5
        failure-rate-threshold: 50
        wait-duration-in-open-state: 10s
        permitted-number-of-calls-in-half-open-state: 3

management:
  endpoints:
    web:
      exposure:
        include: health,info
  health:
    circuitbreakers:
      enabled: true

Apply Circuit Breaker:

@Service
public class EmployeeService {
    
    @Autowired
    private DepartmentClient departmentClient;
    
    @CircuitBreaker(name = "departmentService", fallbackMethod = "getDepartmentFallback")
    public Department getDepartment(Long deptId) {
        return departmentClient.getDepartmentById(deptId);
    }
    
    public Department getDepartmentFallback(Long deptId, Exception ex) {
        Department fallback = new Department();
        fallback.setId(deptId);
        fallback.setName("Default Department");
        return fallback;
    }
}

The circuit breaker monitors calls to getDepartment(). If failures exceed the configured threshold, it opens the circuit and invokes the fallback method instead.910

7. Project Structure Best Practices

Follow a layered architecture within each microservice:18

Entities: Represent domain objects (e.g., Employee, Department).18

Repositories: Handle data access using Spring Data JPA:18

public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    List<Employee> findByDepartmentId(Long departmentId);
}

Services: Contain business logic:18

@Service
public class EmployeeService {
    @Autowired
    private EmployeeRepository employeeRepository;
    
    public Employee findById(Long id) {
        return employeeRepository.findById(id)
            .orElseThrow(() -> new ResourceNotFoundException("Employee not found"));
    }
}

Controllers: Handle HTTP requests.18

DTOs and Mappers: Transform data between layers using MapStruct or manual mapping.18

8. Complete Implementation Example

Here's how all components work together:24

  1. Client Request: A client sends a request to http://localhost:8080/api/employees/1
  2. API Gateway: The gateway receives the request, checks routing rules, and forwards it to employee-service
  3. Service Discovery: The gateway looks up employee-service in the Eureka registry to find available instances
  4. Employee Service: Processes the request and needs department information
  5. Inter-Service Communication: Employee Service calls Department Service via Feign Client
  6. Circuit Breaker: Resilience4j monitors the call; if Department Service is down, it returns a fallback response
  7. Configuration: All services fetch their configuration from the Config Server
  8. Response: The response flows back through the gateway to the client

Key Spring Cloud Components Summary

ComponentPurposeKey Annotation/Class
Spring Cloud Netflix EurekaService Discovery and Registry@EnableEurekaServer, @EnableDiscoveryClient619
Spring Cloud GatewayAPI Gateway with routing and filteringRoute configuration in YAML715
Spring Cloud ConfigCentralized configuration management@EnableConfigServer816
Spring Cloud OpenFeignDeclarative REST client@EnableFeignClients, @FeignClient114
Resilience4jCircuit breaker, retry, rate limiter@CircuitBreaker910
Spring Cloud LoadBalancerClient-side load balancing@LoadBalanced with RestTemplate1

Running the Microservices

Start services in this order:112

  1. Config Server (port 8888)
  2. Eureka Server (port 8761)
  3. Individual Microservices (ports 8081, 8082, etc.)
  4. API Gateway (port 8080)

You can verify service registration by accessing the Eureka dashboard at http://localhost:8761/.116


Additional Enhancements

For production-ready microservices, consider implementing:32

Distributed Tracing: Use Spring Cloud Sleuth with Zipkin or OpenTelemetry with Grafana Tempo for tracking requests across services.2

Log Aggregation: Implement centralized logging using ELK Stack (Elasticsearch, Logstash, Kibana) or Grafana Loki.2

Monitoring: Use Prometheus for metrics collection and Grafana for visualization.2

Security: Implement OAuth2/JWT authentication with Keycloak or Spring Security.2

Containerization: Package services as Docker containers and orchestrate with Kubernetes.2

Event-Driven Architecture: Use Apache Kafka or RabbitMQ for asynchronous communication between services.12

This comprehensive approach using Spring Boot and Spring Cloud provides a robust foundation for building scalable, resilient microservices that follow industry best practices and proven architectural patterns. <span style="display:none">20212223242526272829303132333435363738394041424344454647484950515253545556</span>


<div align="center">⁂</div>

Footnotes

  1. https://www.javaguides.net/2023/01/spring-boot-microservices-architecture.html ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12

  2. https://programmingtechie.com/articles/spring-boot-microservices-tutorial ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10

  3. https://howtodoinjava.com/spring-cloud/spring-cloud-components/ ↩ ↩2

  4. https://dev.to/isaactony/building-your-first-microservice-system-with-spring-boot-a-beginners-guide-3b28 ↩ ↩2 ↩3

  5. https://dzone.com/articles/micro-services-implementation-using-spring-boot-an ↩ ↩2 ↩3 ↩4 ↩5

  6. https://www.geeksforgeeks.org/java/spring-cloud-netflix-eureka/ ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8

  7. https://www.geeksforgeeks.org/java/spring-cloud-gateway/ ↩ ↩2 ↩3 ↩4 ↩5

  8. https://dev.to/markbdsouza/spring-cloud-config-server-step-by-step-14fd ↩ ↩2 ↩3 ↩4 ↩5 ↩6

  9. https://www.geeksforgeeks.org/advance-java/spring-boot-circuit-breaker-pattern-with-resilience4j/ ↩ ↩2 ↩3 ↩4

  10. https://dev.to/tharindufdo/understanding-circuit-breaker-pattern-in-spring-boot-for-resilient-microservices-27bl ↩ ↩2 ↩3 ↩4

  11. https://howtodoinjava.com/spring-cloud/spring-cloud-service-discovery-netflix-eureka/ ↩ ↩2 ↩3

  12. https://www.geeksforgeeks.org/springboot/java-spring-boot-microservices-example-step-by-step-guide/ ↩ ↩2

  13. https://www.interviewplus.ai/questions/java-spring-boot-and-microservices/inter-service-communication-in-spring-boot ↩

  14. https://www.geeksforgeeks.org/system-design/inter-service-communication-in-microservices/ ↩ ↩2 ↩3

  15. https://codingstrain.com/how-to-implement-a-gateway-with-spring-cloud/ ↩ ↩2 ↩3 ↩4

  16. https://www.tutorialspoint.com/spring_boot/spring_boot_cloud_configuration_server.htm ↩ ↩2 ↩3

  17. https://mobisoftinfotech.com/resources/blog/web-programming/tutorial-spring-cloud-config-server-and-client-how-to-set-up-spring-cloud-config-with-jdbc-in-your-microservices-project ↩ ↩2

  18. https://dzone.com/articles/implementation-best-practices-microservice-api-wit ↩ ↩2 ↩3 ↩4 ↩5 ↩6

  19. https://docs.spring.io/spring-cloud-netflix/reference/spring-cloud-netflix.html ↩

  20. https://www.optisolbusiness.com/insight/8-core-components-of-microservice-architecture ↩

  21. https://www.tutorialspoint.com/spring_cloud/spring_cloud_introduction.htm ↩

  22. https://www.javaguides.net/p/spring-boot-microservices-tutorial.html ↩

  23. https://www.linkedin.com/pulse/core-components-microservices-architecture-abid-anjum ↩

  24. https://www.slideshare.net/slideshow/springboot-microservices/96544595 ↩

  25. https://auth0.com/blog/java-spring-boot-microservices/ ↩

  26. https://dev.to/matheusmartinello/developing-microservices-with-spring-boot-and-spring-cloud-5feh ↩

  27. https://www.youtube.com/watch?v=mPPhcU7oWDU ↩

  28. https://www.bacancytechnology.com/blog/spring-boot-microservices ↩

  29. https://www.geeksforgeeks.org/advance-java/java-microservices/ ↩

  30. https://spring.io/projects/spring-cloud ↩

  31. https://www.reddit.com/r/SpringBoot/comments/1if5vis/how_do_i_build_a_microservice_architecture/ ↩

  32. https://igventurelli.io/microservices-with-spring-cloud-an-introduction/ ↩

  33. https://www.youtube.com/watch?v=clBKsG_kpVs ↩

  34. https://www.geeksforgeeks.org/advance-java/spring-cloud-gateway-with-spring-webflux/ ↩

  35. https://www.youtube.com/watch?v=NpdG3lmKJ5g ↩

  36. https://github.com/spring-cloud/spring-cloud-gateway ↩

  37. https://www.baeldung.com/spring-cloud-netflix-eureka ↩

  38. https://docs.spring.io/spring-cloud-gateway/reference/index.html ↩

  39. https://www.youtube.com/watch?v=HFl2dzhVuUo ↩

  40. https://docs.spring.io/spring-cloud-netflix/docs/current/reference/html/ ↩

  41. https://www.youtube.com/watch?v=EKoq98KqvrI ↩

  42. https://www.edureka.co/blog/microservices-with-spring-boot ↩

  43. https://www.youtube.com/watch?v=nT9p44U7TuY ↩

  44. https://dev.to/codegreen/how-would-you-handle-inter-service-communication-in-a-micro-service-architecture-using-spring-boot-kfi ↩

  45. https://github.com/nidhishkrishnan/spring-resilience4j ↩

  46. https://dzone.com/articles/using-spring-config-server ↩

  47. https://www.youtube.com/watch?v=4sL00jc5BPc ↩

  48. https://www.geeksforgeeks.org/java/different-ways-to-establish-communication-between-spring-microservices/ ↩

  49. https://www.youtube.com/watch?v=gb1i4WyWNK4 ↩

  50. https://www.youtube.com/watch?v=3-ChrD3Zosg ↩

  51. https://stackoverflow.com/questions/50506101/spring-boot-how-to-communicate-between-microservices ↩

  52. https://docs.spring.io/spring-cloud-config/reference/server.html ↩

  53. https://docs.spring.io/spring-cloud-circuitbreaker/docs/current/reference/html/ ↩

  54. https://www.youtube.com/watch?v=D_XxZU72yMw ↩

  55. https://www.youtube.com/watch?v=b2ih5RCuxTM ↩

  56. https://docs.spring.io/spring-cloud-circuitbreaker/reference/spring-cloud-circuitbreaker-resilience4j.html ↩