|
| 1 | +# Unicorn Store - Java 25 + Spring Boot 4 |
| 2 | + |
| 3 | +A REST API for managing unicorns, built to showcase modern Java features and container optimization techniques. |
| 4 | + |
| 5 | +## Architecture |
| 6 | + |
| 7 | +``` |
| 8 | +┌─────────────────────────────────────────────────────────────┐ |
| 9 | +│ HTTP Request │ |
| 10 | +└─────────────────────────────────────────────────────────────┘ |
| 11 | + │ |
| 12 | + ▼ |
| 13 | +┌─────────────────────────────────────────────────────────────┐ |
| 14 | +│ RequestContextFilter │ |
| 15 | +│ - Generates unique request ID │ |
| 16 | +│ - Binds to ScopedValue (JEP 506) for request duration │ |
| 17 | +└─────────────────────────────────────────────────────────────┘ |
| 18 | + │ |
| 19 | + ▼ |
| 20 | +┌─────────────────────────────────────────────────────────────┐ |
| 21 | +│ UnicornController │ |
| 22 | +│ - REST endpoints: GET/POST/PUT/DELETE /unicorns │ |
| 23 | +│ - Input validation, error handling │ |
| 24 | +└─────────────────────────────────────────────────────────────┘ |
| 25 | + │ |
| 26 | + ▼ |
| 27 | +┌─────────────────────────────────────────────────────────────┐ |
| 28 | +│ UnicornService │ |
| 29 | +│ - Business logic, validation │ |
| 30 | +│ - Reads request ID from ScopedValue for log correlation │ |
| 31 | +│ - Publishes events to EventBridge │ |
| 32 | +└─────────────────────────────────────────────────────────────┘ |
| 33 | + │ |
| 34 | + ┌───────────────┴───────────────┐ |
| 35 | + ▼ ▼ |
| 36 | +┌─────────────────────────┐ ┌─────────────────────────┐ |
| 37 | +│ UnicornRepository │ │ UnicornPublisher │ |
| 38 | +│ - Spring Data JPA │ │ - EventBridge async │ |
| 39 | +│ - PostgreSQL │ │ - CRUD events │ |
| 40 | +└─────────────────────────┘ └─────────────────────────┘ |
| 41 | +``` |
| 42 | + |
| 43 | +## Project Structure |
| 44 | + |
| 45 | +``` |
| 46 | +src/main/java/com/unicorn/store/ |
| 47 | +├── StoreApplication.java # Spring Boot entry point |
| 48 | +├── context/ |
| 49 | +│ └── RequestContext.java # ScopedValue holder (JEP 506) |
| 50 | +├── filter/ |
| 51 | +│ └── RequestContextFilter.java # Binds request ID to ScopedValue |
| 52 | +├── controller/ |
| 53 | +│ └── UnicornController.java # REST API endpoints |
| 54 | +├── service/ |
| 55 | +│ └── UnicornService.java # Business logic |
| 56 | +├── data/ |
| 57 | +│ ├── UnicornRepository.java # Spring Data JPA |
| 58 | +│ └── UnicornPublisher.java # EventBridge integration |
| 59 | +├── model/ |
| 60 | +│ └── Unicorn.java # JPA entity |
| 61 | +└── config/ |
| 62 | + └── MonitoringConfig.java # Metrics for EKS/ECS |
| 63 | +``` |
| 64 | + |
| 65 | +## Modern Java Features |
| 66 | + |
| 67 | +| Feature | JEP | Location | Description | |
| 68 | +|---------|-----|----------|-------------| |
| 69 | +| Scoped Values | [506](https://openjdk.org/jeps/506) | `RequestContext`, `RequestContextFilter` | Thread-safe request context without ThreadLocal | |
| 70 | +| Flexible Constructor Bodies | [513](https://openjdk.org/jeps/513) | `Unicorn` constructor | Validation before super() call | |
| 71 | +| Unnamed Variables | 456 | catch blocks | `catch (Exception _)` when variable unused | |
| 72 | +| Sequenced Collections | 431 | `UnicornService.getAllUnicorns()` | `getFirst()`, `getLast()` methods | |
| 73 | +| Pattern Matching | 441 | `UnicornService.validateUnicorn()` | Switch with guarded patterns | |
| 74 | +| Virtual Threads | 444 | `application.yaml` | `spring.threads.virtual.enabled: true` | |
| 75 | +| Text Blocks | 378 | `UnicornController` | Multi-line strings | |
| 76 | + |
| 77 | +## Testing |
| 78 | + |
| 79 | +```bash |
| 80 | +# Run all tests (26 total) |
| 81 | +mvn test |
| 82 | + |
| 83 | +# Tests use Testcontainers 2.0 with H2 fallback when Docker unavailable |
| 84 | +``` |
| 85 | + |
| 86 | +**Test Infrastructure:** |
| 87 | +- `@TestInfrastructure` - unified annotation for integration tests |
| 88 | +- PostgreSQL via Testcontainers, H2 fallback without Docker |
| 89 | +- LocalStack for EventBridge |
| 90 | +- Property-based tests with jqwik for validation logic |
| 91 | + |
| 92 | +## Building |
| 93 | + |
| 94 | +```bash |
| 95 | +mvn package # Standard JAR |
| 96 | +mvn package -Pnative # Native image (GraalVM) |
| 97 | +mvn jib:dockerBuild # Container with Jib |
| 98 | +``` |
| 99 | + |
| 100 | +## API Endpoints |
| 101 | + |
| 102 | +| Method | Endpoint | Description | |
| 103 | +|--------|----------|-------------| |
| 104 | +| GET | `/unicorns` | List all unicorns | |
| 105 | +| POST | `/unicorns` | Create unicorn | |
| 106 | +| GET | `/unicorns/{id}` | Get by ID | |
| 107 | +| PUT | `/unicorns/{id}` | Update unicorn | |
| 108 | +| DELETE | `/unicorns/{id}` | Delete unicorn | |
| 109 | +| GET | `/actuator/health` | Health check | |
| 110 | +| GET | `/actuator/prometheus` | Metrics | |
0 commit comments