|
| 1 | +# Copilot Instructions for java.samples.spring.boot |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +This is a RESTful Web Service proof-of-concept built with **Spring Boot 3** targeting **JDK 21 (LTS)**. The application demonstrates a clean, layered architecture implementing a CRUD API for managing books. It uses an in-memory H2 database for data persistence and includes comprehensive test coverage. |
| 6 | + |
| 7 | +**Key URLs:** |
| 8 | + |
| 9 | +- API Server: `http://localhost:9000` |
| 10 | +- Swagger/OpenAPI Docs: `http://localhost:9000/swagger/index.html` |
| 11 | +- Actuator Health: `http://localhost:9001/actuator/health` |
| 12 | + |
| 13 | +## Tech Stack |
| 14 | + |
| 15 | +### Core Framework & Runtime |
| 16 | + |
| 17 | +- **Java**: JDK 21 (LTS) - use modern Java features where appropriate |
| 18 | +- **Spring Boot**: 3.4.4 with starter dependencies (Web, Data JPA, Validation, Cache, Actuator) |
| 19 | +- **Build Tool**: Maven 3.9+ (use `./mvnw` wrapper, NOT system Maven) |
| 20 | +- **Database**: H2 in-memory database (runtime scope) |
| 21 | + |
| 22 | +### Key Dependencies |
| 23 | + |
| 24 | +- **Lombok** 1.18.42: Auto-generate boilerplate code (getters, setters, constructors) |
| 25 | +- **ModelMapper** 3.2.6: Entity-to-DTO mapping |
| 26 | +- **SpringDoc OpenAPI** 2.8.14: API documentation (Swagger UI) |
| 27 | +- **JaCoCo** 0.8.14: Code coverage reporting |
| 28 | +- **AssertJ** 3.27.6: Fluent test assertions |
| 29 | + |
| 30 | +### Testing |
| 31 | + |
| 32 | +- **JUnit 5** (Jupiter): Test framework |
| 33 | +- **Mockito**: Mocking framework |
| 34 | +- **Spring Boot Test**: `@WebMvcTest`, `@DataJpaTest`, etc. |
| 35 | +- **AssertJ**: Preferred assertion library (use over standard JUnit assertions) |
| 36 | + |
| 37 | +### DevOps & CI/CD |
| 38 | + |
| 39 | +- **Docker**: Multi-stage build with Eclipse Temurin Alpine images |
| 40 | +- **Docker Compose**: Local containerized deployment |
| 41 | +- **GitHub Actions**: CI pipeline with coverage reporting (Codecov, Codacy) |
| 42 | +- **Azure Pipelines**: Alternative CI configuration |
| 43 | + |
| 44 | +## Project Structure |
| 45 | + |
| 46 | +``` |
| 47 | +src/main/java/ar/com/nanotaboada/java/samples/spring/boot/ |
| 48 | +├── Application.java # Main entry point, @SpringBootApplication |
| 49 | +├── controllers/ # REST endpoints (@RestController) |
| 50 | +│ └── BooksController.java |
| 51 | +├── services/ # Business logic (@Service, caching) |
| 52 | +│ └── BooksService.java |
| 53 | +├── repositories/ # Data access (@Repository, Spring Data JPA) |
| 54 | +│ └── BooksRepository.java |
| 55 | +└── models/ # Domain entities & DTOs |
| 56 | + ├── Book.java # JPA entity |
| 57 | + ├── BookDTO.java # Data Transfer Object with validation |
| 58 | + └── BooksDataInitializer.java # Seed data |
| 59 | +
|
| 60 | +src/test/java/.../test/ |
| 61 | +├── controllers/ # Controller tests (@WebMvcTest) |
| 62 | +├── services/ # Service layer tests |
| 63 | +├── repositories/ # Repository tests (@DataJpaTest) |
| 64 | +├── BookFakes.java # Test data factory for Book entities |
| 65 | +└── BookDTOFakes.java # Test data factory for BookDTO |
| 66 | +
|
| 67 | +src/main/resources/ |
| 68 | +├── application.properties # Application configuration |
| 69 | +└── logback-spring.xml # Logging configuration |
| 70 | +
|
| 71 | +scripts/ |
| 72 | +├── entrypoint.sh # Docker container entrypoint |
| 73 | +└── healthcheck.sh # Docker health check using Actuator |
| 74 | +``` |
| 75 | + |
| 76 | +**Package Naming Convention**: `ar.com.nanotaboada.java.samples.spring.boot.<layer>` |
| 77 | +**Test Package Convention**: Add `.test` before layer name (e.g., `...samples.spring.boot.test.controllers`) |
| 78 | + |
| 79 | +## Coding Guidelines |
| 80 | + |
| 81 | +### Architecture & Design Patterns |
| 82 | + |
| 83 | +- **Layered Architecture**: Controller → Service → Repository → Entity |
| 84 | +- **DTOs**: Use `BookDTO` for API requests/responses; `Book` entity is internal |
| 85 | +- **Dependency Injection**: Use constructor injection (Lombok `@RequiredArgsConstructor` or explicit constructors) |
| 86 | +- **Caching**: Service layer uses Spring Cache annotations (`@Cacheable`, `@CachePut`, `@CacheEvict`) |
| 87 | +- **Validation**: Use Jakarta Bean Validation annotations on DTOs (`@NotBlank`, `@ISBN`, `@URL`, etc.) |
| 88 | + |
| 89 | +### Java Style |
| 90 | + |
| 91 | +- **Lombok**: Prefer `@Data`, `@RequiredArgsConstructor`, `@NoArgsConstructor`, `@AllArgsConstructor` over manual code |
| 92 | +- **Streams**: Use Java Streams API for collection processing (see `BooksService.retrieveAll()`) |
| 93 | +- **Modern Java**: Leverage JDK 21 features (records, pattern matching, etc.) where beneficial |
| 94 | +- **Comments**: Section dividers used in controllers/services (e.g., `/* HTTP POST */`) |
| 95 | + |
| 96 | +### Testing Conventions |
| 97 | + |
| 98 | +- **Test Class Naming**: `<ClassName>Tests` (plural, e.g., `BooksControllerTests`) |
| 99 | +- **Test Method Naming**: `given<Condition>_when<Action>_then<Expected>` (BDD style) |
| 100 | +- **Assertions**: Use AssertJ fluent assertions (`assertThat(...).isEqualTo(...)`) |
| 101 | +- **Mocking**: Use `@MockBean` for Spring beans, verify interactions with `verify()` |
| 102 | +- **Test Data**: Use fake data factories (`BookFakes`, `BookDTOFakes`) for consistent test data |
| 103 | +- **Display Names**: Use `@DisplayName` for readable test descriptions |
| 104 | + |
| 105 | +### Coverage Exclusions |
| 106 | + |
| 107 | +JaCoCo excludes from coverage (see `pom.xml` and `codecov.yml`): |
| 108 | + |
| 109 | +- `Application.java` (main class) |
| 110 | +- `models/**` package (POJOs with Lombok) |
| 111 | +- Test files and resources |
| 112 | + |
| 113 | +## Build & Run Commands |
| 114 | + |
| 115 | +### Maven Commands (ALWAYS use wrapper) |
| 116 | + |
| 117 | +```bash |
| 118 | +# Clean and compile |
| 119 | +./mvnw clean compile |
| 120 | + |
| 121 | +# Run tests |
| 122 | +./mvnw test |
| 123 | + |
| 124 | +# Run tests with coverage |
| 125 | +./mvnw verify |
| 126 | + |
| 127 | +# Package application |
| 128 | +./mvnw package |
| 129 | + |
| 130 | +# Run application locally |
| 131 | +./mvnw spring-boot:run |
| 132 | + |
| 133 | +# Skip tests during build (use sparingly) |
| 134 | +./mvnw package -DskipTests |
| 135 | +``` |
| 136 | + |
| 137 | +**Critical Requirements**: |
| 138 | + |
| 139 | +- **ALWAYS use `./mvnw` wrapper** (Unix/macOS) or `mvnw.cmd` (Windows), NOT `mvn` |
| 140 | +- **JDK 21 is REQUIRED**: The project targets JDK 21 (LTS). Using newer JDKs (22+) will cause Mockito/ByteBuddy compatibility issues in tests |
| 141 | +- **JAVA_HOME must be set**: Maven wrapper requires JAVA_HOME pointing to JDK 21 installation |
| 142 | + |
| 143 | +### Docker Commands |
| 144 | + |
| 145 | +```bash |
| 146 | +# Build image |
| 147 | +docker compose build |
| 148 | + |
| 149 | +# Start application container |
| 150 | +docker compose up |
| 151 | + |
| 152 | +# Start in detached mode |
| 153 | +docker compose up -d |
| 154 | + |
| 155 | +# Stop and remove containers |
| 156 | +docker compose down |
| 157 | + |
| 158 | +# View logs |
| 159 | +docker compose logs -f |
| 160 | +``` |
| 161 | + |
| 162 | +**Exposed Ports**: |
| 163 | + |
| 164 | +- `9000`: Main API server |
| 165 | +- `9001`: Actuator management endpoints |
| 166 | + |
| 167 | +## Common Tasks & Patterns |
| 168 | + |
| 169 | +### Adding a New REST Endpoint |
| 170 | + |
| 171 | +1. Add method to `BooksController` with appropriate HTTP mapping (`@GetMapping`, `@PostMapping`, etc.) |
| 172 | +2. Annotate with `@Operation` and `@ApiResponses` for OpenAPI documentation |
| 173 | +3. Implement business logic in `BooksService` |
| 174 | +4. Add/update repository method if needed |
| 175 | +5. Write controller tests using `@WebMvcTest` and `MockMvc` |
| 176 | +6. Write service tests with mocked repository |
| 177 | + |
| 178 | +### Adding a New Entity/Resource |
| 179 | + |
| 180 | +1. Create JPA entity in `models/` with `@Entity`, `@Table`, Lombok annotations |
| 181 | +2. Create corresponding DTO with validation annotations |
| 182 | +3. Create repository interface extending `CrudRepository<Entity, ID>` |
| 183 | +4. Create service class with `@Service` and caching annotations |
| 184 | +5. Create controller with `@RestController` and OpenAPI annotations |
| 185 | +6. Create test data factories (e.g., `EntityFakes.java`) |
| 186 | +7. Write comprehensive tests for all layers |
| 187 | + |
| 188 | +### Updating Dependencies |
| 189 | + |
| 190 | +- Dependencies are managed by Dependabot (daily checks) |
| 191 | +- Spring Boot dependencies are grouped and ignored for individual updates |
| 192 | +- Manually update versions in `pom.xml` `<properties>` section if needed |
| 193 | + |
| 194 | +### Running Coverage Reports |
| 195 | + |
| 196 | +```bash |
| 197 | +./mvnw clean verify |
| 198 | +# Report available at: target/site/jacoco/index.html |
| 199 | +``` |
| 200 | + |
| 201 | +## Troubleshooting |
| 202 | + |
| 203 | +### Build Failures |
| 204 | + |
| 205 | +- **Lombok not working**: Ensure annotation processor is enabled in IDE and `maven-compiler-plugin` includes Lombok path |
| 206 | +- **Tests failing**: Check if H2 database is properly initialized; review `BooksDataInitializer.seed()` |
| 207 | +- **Port already in use**: Change `server.port` in `application.properties` or kill process using ports 9000/9001 |
| 208 | +- **JAVA_HOME not set**: Run `export JAVA_HOME=$(/usr/libexec/java_home -v 21)` on macOS or set to JDK 21 path on other systems |
| 209 | +- **JDK version errors**: Project requires JDK 21 (LTS). Using JDK 22+ causes Mockito/ByteBuddy failures like "Java 25 (69) is not supported" |
| 210 | + |
| 211 | +### Docker Issues |
| 212 | + |
| 213 | +- **Container health check failing**: Verify Actuator is accessible at `http://localhost:9001/actuator/health` |
| 214 | +- **Build context too large**: Ensure `.dockerignore` excludes `target/` and `.git/` |
| 215 | + |
| 216 | +### Common Pitfalls |
| 217 | + |
| 218 | +- **Don't use system Maven**: Always use `./mvnw` wrapper |
| 219 | +- **Don't use newer JDKs**: Stick to JDK 21 - newer versions break Mockito in tests |
| 220 | +- **Don't modify `Application.java` coverage**: It's excluded by design |
| 221 | +- **Don't test Lombok-generated code**: Focus on business logic |
| 222 | +- **Repository interfaces**: Custom query methods may not show in coverage (JaCoCo limitation) |
| 223 | + |
| 224 | +## CI/CD Pipeline |
| 225 | + |
| 226 | +### GitHub Actions Workflow (`.github/workflows/maven.yml`) |
| 227 | + |
| 228 | +1. **Verify Job**: Compile, test, generate coverage with `mvn verify` |
| 229 | +2. **Coverage Job**: Upload JaCoCo reports to Codecov and Codacy |
| 230 | +3. **Container Job**: Build and push Docker image to GitHub Container Registry (on `master` push only) |
| 231 | + |
| 232 | +**Required Secrets**: |
| 233 | + |
| 234 | +- `CODECOV_TOKEN`: Codecov integration token |
| 235 | +- `CODACY_PROJECT_TOKEN`: Codacy integration token |
| 236 | +- `GITHUB_TOKEN`: Automatically provided for GHCR push |
| 237 | + |
| 238 | +### Azure Pipelines (`azure-pipelines.yml`) |
| 239 | + |
| 240 | +- Runs on `ubuntu-latest` with JDK 21 |
| 241 | +- Executes `mvn package` and publishes test results |
| 242 | + |
| 243 | +## Contributing |
| 244 | + |
| 245 | +Follow [Conventional Commits](https://www.conventionalcommits.org/): |
| 246 | + |
| 247 | +- `feat:` for new features |
| 248 | +- `fix:` for bug fixes |
| 249 | +- `chore:` for maintenance tasks |
| 250 | + |
| 251 | +**Commit Style**: Keep commits logical and atomic. Squash checkpoint commits before PR. |
| 252 | + |
| 253 | +**PR Requirements**: |
| 254 | + |
| 255 | +- All tests must pass |
| 256 | +- Coverage should not decrease significantly |
| 257 | +- Follow existing code style and patterns |
| 258 | +- Update API documentation if endpoints change |
| 259 | + |
| 260 | +## Additional Resources |
| 261 | + |
| 262 | +- **Code of Conduct**: See `CODE_OF_CONDUCT.md` |
| 263 | +- **Detailed Contributing Guide**: See `CONTRIBUTING.md` |
| 264 | +- **Project Philosophy**: Small, incremental changes over large rewrites (per Linus Torvalds quote in CONTRIBUTING.md) |
0 commit comments