This project serves as a base template for developing microservices in Java with Spring Boot, designed for educational purposes in Cloud Computing courses.
** IMPORTANT:** This is an initial template. Students must complete the functionalities according to the course plan, including:
- Dockerfiles (Week 2) - Create Dockerfiles for each microservice
- Docker Compose (Week 2) - Create docker-compose.yml to orchestrate all services
- Additional unit tests
- CI/CD pipelines (Week 10)
- And other functionalities as per the course plan
Note: Students must implement Dockerfiles and complete docker-compose.yml as part of Week 2 (see course materials).
This is a microservices-based application demonstrating a modern cloud-native architecture. The project consists of four main services:
- API Gateway - Single entry point for all client requests using Spring Cloud Gateway
- User Service - Manages user data and operations
- Product Service - Manages product catalog and inventory
- Order Service - Manages orders with inter-service communication (Kafka + OpenFeign)
┌─────────────┐
│ Client │
└──────┬──────┘
│
▼
┌─────────────────┐
│ API Gateway │ Port: 8080
│ (Spring Gateway)│
└─────┬───────┬───┬───┘
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ User │ │ Product │ │ Order │
│ Service │ │ Service │ │ Service │
│ Port: │ │ Port: │ │ Port: │
│ 8081 │ │ 8082 │ │ 8083 │
└──────────┘ └──────────────┘ └──────────────┘
▲ ▲ │
│ │ │
└──────────────┴──────────────┘
OpenFeign (Sync)
┌──────────────────────────┐
│ Kafka │
│ (Async Event-Driven) │
└──────────────────────────┘
microservices-project/
├── api-gateway/ # API Gateway using Spring Cloud Gateway
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/
│ │ │ │ └── pt/ulusofona/apigateway/
│ │ │ │ ├── ApiGatewayApplication.java
│ │ │ │ └── config/
│ │ │ │ └── GatewayConfig.java
│ │ │ └── resources/
│ │ │ └── application.yml
│ │ └── test/
│ └── pom.xml
├── user-service/ # User management microservice
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/
│ │ │ │ └── pt/ulusofona/userservice/
│ │ │ │ ├── UserServiceApplication.java
│ │ │ │ ├── controller/
│ │ │ │ │ ├── UserController.java
│ │ │ │ │ └── GlobalExceptionHandler.java
│ │ │ │ ├── service/
│ │ │ │ │ └── UserService.java
│ │ │ │ ├── repository/
│ │ │ │ │ └── UserRepository.java
│ │ │ │ ├── model/
│ │ │ │ │ └── User.java
│ │ │ │ └── dto/
│ │ │ │ ├── UserRequest.java
│ │ │ │ └── UserResponse.java
│ │ │ └── resources/
│ │ │ └── application.yml
│ │ └── test/
│ └── pom.xml
├── product-service/ # Product management microservice
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/
│ │ │ │ └── pt/ulusofona/productservice/
│ │ │ │ ├── ProductServiceApplication.java
│ │ │ │ ├── controller/
│ │ │ │ │ ├── ProductController.java
│ │ │ │ │ └── GlobalExceptionHandler.java
│ │ │ │ ├── service/
│ │ │ │ │ └── ProductService.java
│ │ │ │ ├── repository/
│ │ │ │ │ └── ProductRepository.java
│ │ │ │ ├── model/
│ │ │ │ │ └── Product.java
│ │ │ │ └── dto/
│ │ │ │ ├── ProductRequest.java
│ │ │ │ └── ProductResponse.java
│ │ │ └── resources/
│ │ │ └── application.yml
│ │ └── test/
│ └── pom.xml
├── order-service/ # Order management microservice (Kafka + OpenFeign)
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/
│ │ │ │ └── pt/ulusofona/orderservice/
│ │ │ │ ├── OrderServiceApplication.java
│ │ │ │ ├── controller/
│ │ │ │ │ ├── OrderController.java
│ │ │ │ │ └── GlobalExceptionHandler.java
│ │ │ │ ├── service/
│ │ │ │ │ └── OrderService.java
│ │ │ │ ├── repository/
│ │ │ │ │ └── OrderRepository.java
│ │ │ │ ├── model/
│ │ │ │ │ ├── Order.java
│ │ │ │ │ ├── OrderItem.java
│ │ │ │ │ └── OrderStatus.java
│ │ │ │ ├── dto/
│ │ │ │ │ ├── OrderRequest.java
│ │ │ │ │ ├── OrderResponse.java
│ │ │ │ │ └── OrderItemRequest.java
│ │ │ │ ├── client/
│ │ │ │ │ ├── UserServiceClient.java (OpenFeign)
│ │ │ │ │ └── ProductServiceClient.java (OpenFeign)
│ │ │ │ ├── event/
│ │ │ │ │ ├── OrderCreatedEvent.java
│ │ │ │ │ └── OrderStatusChangedEvent.java
│ │ │ │ └── config/
│ │ │ │ └── KafkaConfig.java
│ │ │ └── resources/
│ │ │ └── application.yml
│ │ └── test/
│ └── pom.xml
├── Aulas/ # Course materials and documentation
├── README.md # This file
└── API_EXAMPLES.md # API usage examples
- Java 21 (LTS) - Programming language
- Spring Boot 3.4.0 - Application framework (latest stable version)
- Spring Cloud 2024.0.0 - Latest release train for microservices
- Spring Cloud Gateway - API Gateway for routing and load balancing
- Spring Data JPA - Data persistence abstraction
- Spring Kafka - Asynchronous messaging and event-driven communication
- OpenFeign - Declarative HTTP client for synchronous inter-service communication
- H2 Database - In-memory database for development
- Apache Kafka - Distributed event streaming platform
- JUnit 5 & Mockito - Unit testing framework
- Maven - Dependency management and build tool
- Lombok 1.18.34 - Reduces boilerplate code (latest version)
- Spring Boot Actuator - Monitoring and health checks
- Jakarta Validation - Bean validation framework
- SpringDoc OpenAPI 2.6.0 - API documentation (Swagger UI)
- Micrometer & Prometheus - Metrics collection and observability
Before running this project, ensure you have the following installed:
- Java 21 (LTS) - Required
- Check installation:
java -version - Important: This project requires Java 21. Java 25+ may have compatibility issues with Lombok.
- Download from: Oracle JDK or OpenJDK
- On macOS, you can install via Homebrew:
brew install openjdk@21 - Set JAVA_HOME:
export JAVA_HOME=$(/usr/libexec/java_home -v 21)
- Check installation:
- Maven 3.8+
- Check installation:
mvn -version - Download from: Apache Maven
- Check installation:
- Git
- Check installation:
git --version - Download from: Git
- Check installation:
- Docker (Optional, for running Kafka and services via docker-compose)
- Check installation:
docker --version - Download from: Docker
- Check installation:
- IDE (Recommended: IntelliJ IDEA, Eclipse, or VS Code)
- Note: If using IntelliJ IDEA, ensure Lombok plugin is installed and annotation processing is enabled
Open three separate terminal windows:
Terminal 1 - User Service:
cd user-service
mvn spring-boot:runTerminal 2 - Product Service:
cd product-service
mvn spring-boot:runTerminal 3 - Order Service:
cd order-service
mvn spring-boot:runTerminal 4 - API Gateway:
cd api-gateway
mvn spring-boot:runImportant: Before starting the services, ensure Kafka is running:
# Using Docker Compose (recommended)
docker-compose up -d zookeeper kafka
# Or install Kafka locally and start it# Build all services
mvn clean package
# Run User Service
cd user-service
java -jar target/user-service-1.0.0.jar
# Run Product Service (in another terminal)
cd product-service
java -jar target/product-service-1.0.0.jar
# Run API Gateway (in another terminal)
cd api-gateway
java -jar target/api-gateway-1.0.0.jarOnce all services are running, they will be available at:
- API Gateway: http://localhost:8080
- User Service: http://localhost:8081
- Product Service: http://localhost:8082
- Order Service: http://localhost:8083
Kafka should be running on:
- Kafka Broker: localhost:9092
- Zookeeper: localhost:2181
All requests should go through the API Gateway:
GET /api/users- List all usersGET /api/users/{id}- Get user by IDPOST /api/users- Create new userPUT /api/users/{id}- Update userDELETE /api/users/{id}- Delete userGET /api/products- List all productsGET /api/products/{id}- Get product by IDPOST /api/products- Create new productPUT /api/products/{id}- Update productDELETE /api/products/{id}- Delete productGET /api/orders- List all ordersGET /api/orders/{id}- Get order by IDGET /api/orders/user/{userId}- Get orders by user IDPOST /api/orders- Create new orderPUT /api/orders/{id}/status- Update order status
Direct access to User Service (bypassing gateway):
GET /users- List all usersGET /users/{id}- Get user by IDPOST /users- Create new userPUT /users/{id}- Update userDELETE /users/{id}- Delete user
Direct access to Product Service (bypassing gateway):
GET /products- List all productsGET /products/{id}- Get product by IDPOST /products- Create new productPUT /products/{id}- Update productDELETE /products/{id}- Delete product
Direct access to Order Service (bypassing gateway):
GET /orders- List all ordersGET /orders/{id}- Get order by IDGET /orders/user/{userId}- Get orders by user IDPOST /orders- Create new orderPUT /orders/{id}/status?status={status}- Update order status
Execute tests for each service:
# Set Java 21 (if not default)
export JAVA_HOME=$(/usr/libexec/java_home -v 21)
# Run User Service tests
cd user-service
mvn test
# Run Product Service tests
cd product-service
mvn test
# Run Order Service tests
cd order-service
mvn test
# Run API Gateway tests
cd api-gateway
mvn test
# Run all tests from root
mvn test -pl user-service,product-service,order-service,api-gatewayThe project uses JaCoCo for coverage. Each module enforces a minimum line coverage (85% for services, 70% for API Gateway). After running mvn test, open the report at target/site/jacoco/index.html in each module.
- User Service: Controller tests (CRUD + validation + exception handler), Service tests (all branches including email-in-use), GlobalExceptionHandler, Application context
- Product Service: Controller tests (CRUD + search + exception handler), Service tests (including null stockQuantity branches), OrderEventConsumer (success, product not found, insufficient stock, multiple items, save failure), GlobalExceptionHandler, Application context
- Order Service: Controller tests (create, validation, get by id, exception handler), Service tests (create/get/update, user/product not found, insufficient stock), GlobalExceptionHandler, Order model (addOrderItem, calculateTotal), Application context
- API Gateway: Application context (loads GatewayConfig)
All tests use:
- JUnit 5 for test framework
- Mockito for mocking dependencies
- Spring Boot Test for integration tests
- JaCoCo for coverage reports and minimum coverage checks
- MockMvc for controller testing
- Spring Kafka Test for Kafka integration testing
- ✅ OpenAPI/Swagger Documentation - Complete API documentation for all services
- ✅ Observability - Prometheus metrics via Actuator
- ✅ Comprehensive Testing - Unit and integration tests with high coverage
- ✅ Error Handling - Global exception handlers with proper HTTP status codes
- ✅ Validation - Jakarta Validation for request validation
- ✅ Modern Dependencies - Latest stable versions of all frameworks
- ✅ API Gateway - Centralized routing with order service support
This project demonstrates two types of inter-service communication:
Order Service uses OpenFeign to make synchronous HTTP calls to:
- User Service - Validates user existence before creating orders
- Product Service - Validates products and fetches product details
Example Flow:
Order Service → (OpenFeign) → User Service: Validate user
Order Service → (OpenFeign) → Product Service: Validate products & get details
Order Service: Create order
Order Service publishes events to Kafka topics:
order-created- Published when a new order is createdorder-status-changed- Published when order status changes
Product Service consumes events from Kafka:
- Listens to
order-createdtopic to update inventory
Example Flow:
Order Service: Creates order → Publishes OrderCreatedEvent to Kafka
Product Service: Consumes event → Updates product inventory
Each microservice follows a layered architecture pattern:
┌─────────────────────┐
│ Controller Layer │ REST API endpoints
├─────────────────────┤
│ Service Layer │ Business logic
├─────────────────────┤
│ Repository Layer │ Data access
├─────────────────────┤
│ Model Layer │ Entity/Domain models
└─────────────────────┘
- Controller Layer - Handles HTTP requests/responses, input validation
- Service Layer - Contains business logic, transaction management
- Repository Layer - Data access abstraction, database operations
- Model Layer - Entity classes representing database tables
- DTO Layer - Data Transfer Objects for API communication
- Create Dockerfile for each microservice
- Create docker-compose.yml for local orchestration
- Test execution with Docker Compose
- Implement multi-stage builds for optimization
- Build Docker images
- Push to DockerHub or institutional repository
- Pull and execute in another environment
- Tag images with version numbers
- Configure AWS CLI
- Create automation scripts
- Test AWS service interactions
- Create VPC and subnets
- Configure route tables
- Set up security groups
- Configure internet gateway
- Create EC2 instance
- Manual container deployment on EC2
- Configure security groups for services
- Test remote access
- Replace H2 with AWS RDS
- Configure remote database connection
- Update connection strings
- Test database connectivity
- Create infrastructure with Terraform
- Modularize Terraform code
- Implement state management
- Create reusable modules
- Create GitHub Actions pipeline
- Implement automated deployment
- Add automated testing
- Configure deployment environments
- Integrate SQS for messaging
- Implement event-driven architecture
- Create message producers and consumers
- Handle asynchronous communication
- Create Ansible playbooks
- Automate configuration management
- Implement infrastructure provisioning
- Configure application deployment
See API_EXAMPLES.md for practical API usage examples with curl commands and request/response samples.
- Java Version: This project requires Java 21 (LTS). Java 25+ has compatibility issues with Lombok. See COMPILATION.md for details.
- Database: Currently uses H2 in-memory database. Should be replaced with AWS RDS in Week 7.
- Docker (Week 2):
- Students must create Dockerfiles for each service (user-service, product-service, order-service, api-gateway)
- Students must complete docker-compose.yml in the project root (TODO structure is provided)
- See
Aulas/Week-02/for detailed instructions
- Tests: Comprehensive unit tests are included (44+ test methods). All tests pass with Java 21.
- CI/CD: Pipelines must be created by students in Week 10.
- Kafka: Required for Order Service. Students will configure this in docker-compose.yml (Week 2).
- Inter-Service Communication:
- Synchronous: OpenFeign (Order Service → User/Product Services)
- Asynchronous: Kafka (Order Service publishes events, Product Service consumes)
- Tests: Basic tests are included as examples. Students should expand test coverage.
- CI/CD: Pipelines must be created by students in Week 10.
- Configuration: Service URLs are hardcoded for local development. Will be updated when Docker Compose is implemented.
Spring Boot Actuator is configured for health monitoring and observability:
- User Service: http://localhost:8081/actuator/health
- Product Service: http://localhost:8082/actuator/health
- Order Service: http://localhost:8083/actuator/health
- API Gateway: http://localhost:8080/actuator/health
- User Service: http://localhost:8081/actuator/prometheus
- Product Service: http://localhost:8082/actuator/prometheus
- Order Service: http://localhost:8083/actuator/prometheus
- API Gateway: http://localhost:8080/actuator/prometheus
- User Service: http://localhost:8081/swagger-ui.html
- Product Service: http://localhost:8082/swagger-ui.html
- Order Service: http://localhost:8083/swagger-ui.html
- API Gateway: http://localhost:8080/swagger-ui.html
- User Service: http://localhost:8081/api-docs
- Product Service: http://localhost:8082/api-docs
- Order Service: http://localhost:8083/api-docs
- API Gateway: http://localhost:8080/api-docs
- Follow Java naming conventions
- Use meaningful variable and method names
- Add Javadoc comments for public methods
- Keep methods focused and single-purpose
- Write unit tests for service layer
- Write integration tests for controllers
- Aim for at least 70% code coverage
- Use meaningful test method names
- Use appropriate HTTP status codes
- Provide meaningful error messages
- Log errors appropriately
- Handle exceptions gracefully
docker-compose.yml file and create Dockerfiles for each service as part of Week 2 exercises.
Once you've completed docker-compose.yml and built images from your Dockerfiles:
# Start all services (Kafka, Zookeeper, and all microservices)
docker-compose up -d
# View logs
docker-compose logs -f
# Stop all services
docker-compose downNote:
- Make sure Docker is installed and running
- You must create Dockerfiles for each service first (Week 2)
- See
Aulas/Week-02/for detailed instructions
If services cannot connect to Kafka:
# Check if Kafka is running
docker ps | grep kafka
# Check Kafka logs
docker-compose logs kafka
# Verify Kafka is accessible
telnet localhost 9092If you get a "port already in use" error:
# Find process using port
lsof -i :8080 # or 8081, 8082
# Kill process
kill -9 <PID>- Ensure H2 is properly configured in application.yml
- Check database URL and credentials
- Verify Spring Data JPA is properly configured
- Verify all services are running
- Check API Gateway routing configuration
- Verify service URLs in GatewayConfig.java
This is an educational template. Students should complete functionalities according to the course plan.
This project is for educational purposes.