Lorem ipsum text processor based on the loripsum.net API.
A Spring Boot microservices example showing how to fetch and process dummy text, publish results to Kafka, and expose a pageable reports history via REST. Includes Swagger UI, health checks, metrics, and a ready-to-run demo stack.
- Runtime: Java 21 (with Java 21 features), Spring Boot 3.5.6, Spring Framework 6.x
- Web Server: Undertow (replacing Tomcat for better performance)
- Messaging: Apache Kafka (Confluent 7.8.3) with Spring Kafka
- Database: PostgreSQL 16.6 with Liquibase migrations
- Caching: EhCache with Spring Cache abstraction
- Build Tool: Maven 3.x with multi-module structure
- Code Quality: Checkstyle, PMD, SpotBugs, Qulice
- Testing: JUnit 5, Testcontainers, WireMock, Spring Boot Test
- Code Coverage: JaCoCo (minimum 80% coverage)
- Monitoring: Micrometer with Prometheus metrics
- Logging: Logback with structured JSON logging (Logstash encoder)
- Tracing: Micrometer Tracing with Brave
- Dashboards: Grafana with pre-configured dashboards
- Code Analysis: SonarQube integration
- Containerization: Docker & Docker Compose
| Module | Description | Default port | Main endpoint |
|---|---|---|---|
words-processing |
Calls loripsum.net, analyzes text, publishes a report to Kafka and returns it | 8085 | GET /api/v1/text?p={1..10}&l={short,medium,long,verylong} |
reports-history |
Consumes reports from Kafka and stores in Postgres; exposes pageable history | 8086 | GET /api/v1/history?page=0&size=20&sort=id,desc |
- Words Processing API: http://localhost:8085/swagger-ui.html
- Reports History API: http://localhost:8086/swagger-ui.html
- Words Processing: http://localhost:8085/v3/api-docs
- Reports History: http://localhost:8086/v3/api-docs
- Development Guide: development.md - Detailed development setup and guidelines
- API Reference: api-reference.md - Complete API reference documentation
Run the pre-built images with all dependencies (Kafka, Postgres) in one go:
docker compose -f docker-compose.yml upOnce started:
- Words Processing API:
http://localhost:8085/api/v1/text - Reports History API:
http://localhost:8086/api/v1/history
Example calls:
curl "http://localhost:8085/api/v1/text?p=2&l=short"
curl "http://localhost:8086/api/v1/history?page=0&size=10&sort=id,desc"Stop the demo stack:
docker compose -f docker-compose.yml down- Git: Version control
- JDK 21+: OpenJDK or Oracle JDK (Java 21 features supported)
- Docker & Docker Compose: For infrastructure services
- Maven 3.8+: Build tool (wrapper included)
- IDE: IntelliJ IDEA, VS Code, or Eclipse with Spring Boot support
- Records: Immutable DTOs and value objects
- Pattern Matching: Enhanced switch expressions
- Text Blocks: Improved string handling
- Sealed Classes: Restricted inheritance hierarchies
- Virtual Threads: Project Loom integration (when available)
Clone the repo:
git clone https://github.com/IQKV/sample-lorem.git
cd sample-loremdocker compose -f compose.yaml up -dThis exposes Postgres on localhost:5432 and Kafka on localhost:9092. Optional services: Prometheus, Grafana, SonarQube (see compose.yaml).
./mvnw -q -DskipTests package- Words Processing:
java -jar words-processing/target/*.jarOpen Swagger UI: http://localhost:8085/swagger-ui.html
- Reports History:
java -jar reports-history/target/*.jarOpen Swagger UI: http://localhost:8086/swagger-ui.html
curl "http://localhost:8085/api/v1/text?p=3&l=medium"
curl "http://localhost:8086/api/v1/history?page=0&size=5&sort=id,desc"This repository follows a Maven aggregator pattern (packaging=pom) with a clean separation of concerns:
sample-lorem (com.iqkv:sample-lorem:0.25.0-SNAPSHOT)
ββ shared/ # Common utilities, DTOs, Kafka configuration
β ββ sample-lorem-shared # Shared across all modules
ββ words-processing/ # Text processing microservice
β ββ sample-lorem-words-processing # Port 8085
ββ reports-history/ # Report storage microservice
ββ sample-lorem-reports-history # Port 8086
βββββββββββββββββββ ββββββββββββββββββββ
β words-processingβ β reports-history β
β β β β
β β’ REST API β β β’ REST API β
β β’ Text analysis β β β’ Kafka consumer β
β β’ Kafka producerβ β β’ PostgreSQL β
β β’ External API β β β’ JPA/Hibernate β
βββββββββββ¬ββββββββ βββββββββββ¬βββββββββ
β β
ββββββββ¬ββββββββββββββ¬βββ
β β
βββββββββΌββββββββββββββΌββββ
β shared β
β β
β β’ Common DTOs β
β β’ Kafka configuration β
β β’ Validation utilities β
β β’ OpenAPI documentation β
β β’ Actuator endpoints β
βββββββββββββββββββββββββββ
- Shared Module: Contains common utilities, DTOs, and configurations to avoid duplication
- Service Independence: Each service can be built, tested, and deployed independently
- Event-Driven Communication: Services communicate via Kafka for loose coupling
- Database per Service: Each service owns its data (reports-history uses PostgreSQL)
- Observability: All modules include Micrometer metrics and structured logging
- Build everything:
./mvnw -q clean install- Build and run only
words-processing, building its deps (-am):
./mvnw -q -pl words-processing -am clean package
java -jar words-processing/target/*.jar- Build and run only
reports-history:
./mvnw -q -pl reports-history -am clean package
java -jar reports-history/target/*.jar- Run tests with Testcontainers profile for all modules:
./mvnw verify -P use-testcontainers- Limit actions to a module (e.g., unit tests only for
shared):
./mvnw -q -pl shared test- Start
words-processing(build dependencies and run):
./mvnw -q -pl words-processing -am spring-boot:run- Start
reports-history:
./mvnw -q -pl reports-history -am spring-boot:run- Optionally enable the
devprofile while running:
./mvnw -q -pl words-processing -am spring-boot:run -Dspring-boot.run.profiles=dev
./mvnw -q -pl reports-history -am spring-boot:run -Dspring-boot.run.profiles=devdev: adds Spring Boot DevTools to the service modulesuse-testcontainers: enables embedded Kafka/Postgres testinguse-qulice: enables additional static analysis checks
Applications support environment variables (see words-processing/src/main/resources/application.yml and reports-history/src/main/resources/application.yml). Common ones:
| Variable | Description | Default |
|---|---|---|
SERVER_PORT |
HTTP port | 8085 (words), 8086 (history) |
KAFKA_BOOTSTRAP_SERVERS |
Kafka broker list | localhost:9092 |
KAFKA_SECURITY_PROTOCOL |
Security protocol | PLAINTEXT |
KAFKA_TOPIC_WORDS_PROCESSED |
Topic for processed reports | words.processed |
KAFKA_TOPIC_PARTITIONS_WORDS_PROCESSED |
Topic partitions | 4 |
KAFKA_CONSUMER_THREADS |
Consumer threads (history) | 4 |
KAFKA_CONSUMERS_GROUP |
Consumer group (history) | reports-history |
KAFKA_ADMIN_CREATES_TOPICS |
Auto-create topics on startup | true |
DATASOURCE_URL |
JDBC URL (history) | jdbc:postgresql://localhost:5432/lorem_db |
DATASOURCE_USERNAME |
DB username (history) | postgres |
DATASOURCE_PASSWORD |
DB password (history) | postgres |
- Input Validation: Bean Validation (JSR-303) with custom validators
- CORS Configuration: Configurable cross-origin resource sharing
- Actuator Security: Production-ready endpoint security
- Dependency Scanning: OWASP dependency check integration
# Check for security vulnerabilities
./mvnw org.owasp:dependency-check-maven:check
# Security headers validation
curl -I http://localhost:8085/api/v1/text- Development: Relaxed CORS, debug endpoints enabled
- Production: Strict CORS, minimal actuator endpoints, HTTPS only
- Application Metrics: Custom business metrics via Micrometer
- JVM Metrics: Memory, GC, thread pools automatically exposed
- Database Metrics: Connection pool, query performance via Hibernate
- Kafka Metrics: Producer/consumer lag, throughput metrics
# Start monitoring infrastructure
docker compose -f compose.yaml up -d prometheus grafana
# Access dashboards
open http://localhost:3000 # Grafana (admin/changeme)
open http://localhost:9090 # Prometheus- Application Overview: Request rates, response times, error rates
- JVM Monitoring: Memory usage, GC performance, thread metrics
- Database Performance: Connection pools, query execution times
- Kafka Monitoring: Topic throughput, consumer lag, partition metrics
- Structured Logging: JSON format with correlation IDs
- Log Levels: Environment-specific configuration
- Centralized Logging: Loki integration available
# Run all tests with Testcontainers
./mvnw verify -P use-testcontainers
# Run only unit tests
./mvnw test
# Run integration tests
./mvnw integration-test
# Generate coverage report
./mvnw jacoco:report- Unit Tests: JUnit 5, Mockito, Hamcrest
- Integration Tests: Spring Boot Test, Testcontainers (PostgreSQL, Kafka)
- API Testing: MockMvc, WireMock for external service mocking
- Architecture Tests: ArchUnit for enforcing architectural constraints
- Minimum Code Coverage: 80% (enforced by JaCoCo)
- Branch Coverage: 85% minimum
- Mutation Testing: Available via PIT testing
- Static Analysis: Checkstyle, PMD, SpotBugs
- Undertow Server: Non-blocking I/O for better throughput
- Connection Pooling: HikariCP for optimal database connections
- Caching Strategy: EhCache for frequently accessed data
- Kafka Partitioning: 4 partitions for parallel processing
# Application metrics
curl http://localhost:8085/actuator/metrics
curl http://localhost:8086/actuator/metrics
# Health checks
curl http://localhost:8085/actuator/health
curl http://localhost:8086/actuator/health
# Prometheus metrics
curl http://localhost:8085/actuator/prometheus- Horizontal Scaling: Stateless services support multiple instances
- Database Scaling: Read replicas supported via Spring profiles
- Kafka Consumer Groups: Multiple consumer instances for load distribution
- Caching: Distributed caching ready (Redis integration available)
The code follows the Google Java Style and is checked by Checkstyle, PMD, and SpotBugs. Optional SonarQube is available in compose.yaml.
The project includes Cursor Editor rules for consistent development practices:
- Java Language Best Practices: Rules for code style, performance, security, and testing to ensure clean, maintainable, and efficient Java code.
- Spring Boot Best Practices: Guidelines for proper implementation of Spring Boot patterns, dependency injection, configuration, and RESTful API design.
These rules are available in the .cursor/rules directory and are automatically applied when using the Cursor Editor.
# Clear Maven cache
./mvnw dependency:purge-local-repository
# Skip tests if needed
./mvnw clean install -DskipTests
# Check for dependency conflicts
./mvnw dependency:tree# Check application health
curl http://localhost:8085/actuator/health
curl http://localhost:8086/actuator/health
# View application logs
docker logs lorem-demo-words-processing
docker logs lorem-demo-reports-history
# Check Kafka connectivity
docker exec -it lorem-demo-kafka kafka-topics --bootstrap-server localhost:9092 --list# Connect to PostgreSQL
docker exec -it lorem-demo-postgres psql -U postgres -d lorem_db
# Check database migrations
./mvnw liquibase:status -pl reports-history
# Reset database (development only)
docker compose -f compose.yaml down -v
docker compose -f compose.yaml up -d postgres# JVM tuning for containers
export JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"
# Enable virtual threads (Java 21+)
export JAVA_OPTS="$JAVA_OPTS --enable-preview"
# Database connection tuning
export DATASOURCE_HIKARI_MAXIMUM_POOL_SIZE=20
export DATASOURCE_HIKARI_MINIMUM_IDLE=5# Clean build artifacts
./mvnw clean
# Stop and remove containers
docker compose -f compose.yaml down
# Remove volumes (data loss!)
docker compose -f compose.yaml down -v
# Clean Docker system
docker system prune -f# Health check endpoints
curl http://localhost:8085/actuator/health/liveness
curl http://localhost:8086/actuator/health/readiness
# Graceful shutdown
curl -X POST http://localhost:8085/actuator/shutdown
curl -X POST http://localhost:8086/actuator/shutdown
# Log rotation and cleanup
find logs/ -name "*.log" -mtime +7 -deleteLicensed under the Apache License, Version 2.0. See LICENSE.