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.propertiesdepartment-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
- Client Request: A client sends a request to
http://localhost:8080/api/employees/1 - API Gateway: The gateway receives the request, checks routing rules, and forwards it to
employee-service - Service Discovery: The gateway looks up
employee-servicein the Eureka registry to find available instances - Employee Service: Processes the request and needs department information
- Inter-Service Communication: Employee Service calls Department Service via Feign Client
- Circuit Breaker: Resilience4j monitors the call; if Department Service is down, it returns a fallback response
- Configuration: All services fetch their configuration from the Config Server
- Response: The response flows back through the gateway to the client
Key Spring Cloud Components Summary
| Component | Purpose | Key Annotation/Class |
|---|---|---|
| Spring Cloud Netflix Eureka | Service Discovery and Registry | @EnableEurekaServer, @EnableDiscoveryClient619 |
| Spring Cloud Gateway | API Gateway with routing and filtering | Route configuration in YAML715 |
| Spring Cloud Config | Centralized configuration management | @EnableConfigServer816 |
| Spring Cloud OpenFeign | Declarative REST client | @EnableFeignClients, @FeignClient114 |
| Resilience4j | Circuit breaker, retry, rate limiter | @CircuitBreaker910 |
| Spring Cloud LoadBalancer | Client-side load balancing | @LoadBalanced with RestTemplate1 |
Running the Microservices
Start services in this order:112
- Config Server (port 8888)
- Eureka Server (port 8761)
- Individual Microservices (ports 8081, 8082, etc.)
- 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
-
https://www.javaguides.net/2023/01/spring-boot-microservices-architecture.html ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12
-
https://programmingtechie.com/articles/spring-boot-microservices-tutorial ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10
-
https://howtodoinjava.com/spring-cloud/spring-cloud-components/ ↩ ↩2
-
https://dev.to/isaactony/building-your-first-microservice-system-with-spring-boot-a-beginners-guide-3b28 ↩ ↩2 ↩3
-
https://dzone.com/articles/micro-services-implementation-using-spring-boot-an ↩ ↩2 ↩3 ↩4 ↩5
-
https://www.geeksforgeeks.org/java/spring-cloud-netflix-eureka/ ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
https://www.geeksforgeeks.org/java/spring-cloud-gateway/ ↩ ↩2 ↩3 ↩4 ↩5
-
https://dev.to/markbdsouza/spring-cloud-config-server-step-by-step-14fd ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
https://www.geeksforgeeks.org/advance-java/spring-boot-circuit-breaker-pattern-with-resilience4j/ ↩ ↩2 ↩3 ↩4
-
https://dev.to/tharindufdo/understanding-circuit-breaker-pattern-in-spring-boot-for-resilient-microservices-27bl ↩ ↩2 ↩3 ↩4
-
https://howtodoinjava.com/spring-cloud/spring-cloud-service-discovery-netflix-eureka/ ↩ ↩2 ↩3
-
https://www.geeksforgeeks.org/springboot/java-spring-boot-microservices-example-step-by-step-guide/ ↩ ↩2
-
https://www.interviewplus.ai/questions/java-spring-boot-and-microservices/inter-service-communication-in-spring-boot ↩
-
https://www.geeksforgeeks.org/system-design/inter-service-communication-in-microservices/ ↩ ↩2 ↩3
-
https://codingstrain.com/how-to-implement-a-gateway-with-spring-cloud/ ↩ ↩2 ↩3 ↩4
-
https://www.tutorialspoint.com/spring_boot/spring_boot_cloud_configuration_server.htm ↩ ↩2 ↩3
-
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
-
https://dzone.com/articles/implementation-best-practices-microservice-api-wit ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
https://docs.spring.io/spring-cloud-netflix/reference/spring-cloud-netflix.html ↩
-
https://www.optisolbusiness.com/insight/8-core-components-of-microservice-architecture ↩
-
https://www.tutorialspoint.com/spring_cloud/spring_cloud_introduction.htm ↩
-
https://www.javaguides.net/p/spring-boot-microservices-tutorial.html ↩
-
https://www.linkedin.com/pulse/core-components-microservices-architecture-abid-anjum ↩
-
https://www.slideshare.net/slideshow/springboot-microservices/96544595 ↩
-
https://dev.to/matheusmartinello/developing-microservices-with-spring-boot-and-spring-cloud-5feh ↩
-
https://www.bacancytechnology.com/blog/spring-boot-microservices ↩
-
https://www.geeksforgeeks.org/advance-java/java-microservices/ ↩
-
https://www.reddit.com/r/SpringBoot/comments/1if5vis/how_do_i_build_a_microservice_architecture/ ↩
-
https://igventurelli.io/microservices-with-spring-cloud-an-introduction/ ↩
-
https://www.geeksforgeeks.org/advance-java/spring-cloud-gateway-with-spring-webflux/ ↩
-
https://docs.spring.io/spring-cloud-gateway/reference/index.html ↩
-
https://docs.spring.io/spring-cloud-netflix/docs/current/reference/html/ ↩
-
https://www.edureka.co/blog/microservices-with-spring-boot ↩
-
https://dev.to/codegreen/how-would-you-handle-inter-service-communication-in-a-micro-service-architecture-using-spring-boot-kfi ↩
-
https://www.geeksforgeeks.org/java/different-ways-to-establish-communication-between-spring-microservices/ ↩
-
https://stackoverflow.com/questions/50506101/spring-boot-how-to-communicate-between-microservices ↩
-
https://docs.spring.io/spring-cloud-config/reference/server.html ↩
-
https://docs.spring.io/spring-cloud-circuitbreaker/docs/current/reference/html/ ↩
-
https://docs.spring.io/spring-cloud-circuitbreaker/reference/spring-cloud-circuitbreaker-resilience4j.html ↩