|
1 | | -# Copilot Instructions |
| 1 | +# GitHub Copilot Instructions |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +REST API for managing football players built with Java and Spring Boot. Implements CRUD operations with a layered architecture, Spring Data JPA + SQLite, Bean Validation, Spring Cache, and Swagger documentation. Part of a cross-language comparison study (.NET, Go, Python, Rust, TypeScript). |
| 6 | + |
| 7 | +## Tech Stack |
| 8 | + |
| 9 | +- **Language**: Java 25 (LTS, required) |
| 10 | +- **Framework**: Spring Boot 4.0.0 (Spring MVC) |
| 11 | +- **ORM**: Spring Data JPA + Hibernate |
| 12 | +- **Database**: SQLite (file-based runtime, in-memory for tests) |
| 13 | +- **Build**: Maven 3 — always use `./mvnw` wrapper |
| 14 | +- **Validation**: Bean Validation (JSR-380) |
| 15 | +- **Caching**: Spring `@Cacheable` (1-hour TTL) |
| 16 | +- **Mapping**: ModelMapper |
| 17 | +- **Logging**: SLF4J |
| 18 | +- **Testing**: JUnit 5 + AssertJ + MockMvc + Mockito |
| 19 | +- **Coverage**: JaCoCo |
| 20 | +- **API Docs**: SpringDoc OpenAPI 3 (Swagger) |
| 21 | +- **Boilerplate**: Lombok |
| 22 | +- **Containerization**: Docker |
| 23 | + |
| 24 | +## Structure |
| 25 | + |
| 26 | +```text |
| 27 | +src/main/java/ |
| 28 | +├── controllers/ — HTTP handlers; delegate to services, no business logic [HTTP layer] |
| 29 | +├── services/ — Business logic + @Cacheable caching [business layer] |
| 30 | +├── repositories/ — Spring Data JPA with derived queries [data layer] |
| 31 | +├── models/ — Player entity + DTOs |
| 32 | +└── converters/ — ModelMapper entity ↔ DTO transformations |
| 33 | +src/main/resources/ — application.properties, Logback config |
| 34 | +src/test/java/ — test classes mirroring main structure |
| 35 | +src/test/resources/ — test config, schema (ddl.sql), seed data (dml.sql) |
| 36 | +storage/ — SQLite database file (runtime) |
| 37 | +``` |
| 38 | + |
| 39 | +**Layer rule**: `Controller → Service → Repository → JPA`. Controllers must not access repositories directly. Business logic must not live in controllers. |
2 | 40 |
|
3 | | -## Project Overview |
| 41 | +## Coding Guidelines |
4 | 42 |
|
5 | | -REST API for managing football players built with Java 25 and Spring Boot 4. Demonstrates layered architecture (Controller → Service → Repository), Spring Data JPA with SQLite, comprehensive validation, caching, and Swagger documentation. |
| 43 | +- **Naming**: camelCase (methods/variables), PascalCase (classes), UPPER_SNAKE_CASE (constants) |
| 44 | +- **Files**: class name matches file name |
| 45 | +- **DI**: Constructor injection via Lombok `@RequiredArgsConstructor`; never field injection |
| 46 | +- **Annotations**: `@RestController`, `@Service`, `@Repository`, `@Entity`, `@Data`/`@Builder`/`@AllArgsConstructor` (Lombok) |
| 47 | +- **Transactions**: `@Transactional(readOnly = true)` on read service methods; `@Transactional` on writes |
| 48 | +- **Errors**: `@ControllerAdvice` for global exception handling |
| 49 | +- **Logging**: SLF4J only; never `System.out.println` |
| 50 | +- **DTOs**: Never expose entities directly in controllers — always use DTOs |
| 51 | +- **Tests**: BDD Given-When-Then naming (`givenX_whenY_thenZ`); AssertJ BDD style (`then(result).isNotNull()`); in-memory SQLite auto-clears after each test |
| 52 | +- **Avoid**: field injection, `new` for Spring beans, missing `@Transactional`, exposing entities in controllers, hardcoded configuration |
6 | 53 |
|
7 | | -## Quick Start |
| 54 | +## Commands |
| 55 | + |
| 56 | +### Quick Start |
8 | 57 |
|
9 | 58 | ```bash |
10 | | -# Development |
11 | | -./mvnw spring-boot:run # Run with hot reload (port 9000) |
12 | | -./mvnw clean test # Run tests |
13 | | -./mvnw clean test jacoco:report # Test with coverage |
14 | | - |
15 | | -# Docker |
16 | | -docker compose up # Start in container |
17 | | -docker compose down -v # Reset database |
18 | | - |
19 | | -# Documentation |
20 | | -http://localhost:9000/swagger/index.html # API docs |
21 | | -http://localhost:9001/actuator/health # Health check |
| 59 | +./mvnw spring-boot:run # port 9000 |
| 60 | +./mvnw clean test # run tests |
| 61 | +./mvnw clean test jacoco:report # tests + coverage |
| 62 | +open target/site/jacoco/index.html # view coverage report |
| 63 | +docker compose up |
| 64 | +docker compose down -v |
22 | 65 | ``` |
23 | 66 |
|
24 | | -## Stack |
| 67 | +### Pre-commit Checks |
25 | 68 |
|
26 | | -- Java 25 (LTS, required) |
27 | | -- Spring Boot 4.0.0 (Spring MVC) |
28 | | -- Spring Data JPA + Hibernate |
29 | | -- SQLite (file-based runtime, in-memory tests) |
30 | | -- Maven 3 (use `./mvnw` wrapper) |
31 | | -- Bean Validation (JSR-380) |
32 | | -- Spring Cache (1-hour TTL) |
33 | | -- JUnit 5 + AssertJ + MockMvc |
34 | | -- JaCoCo (coverage) |
35 | | -- SpringDoc OpenAPI 3 (Swagger) |
36 | | -- Lombok (boilerplate reduction) |
| 69 | +1. `./mvnw clean install` — must succeed |
| 70 | +2. All tests pass |
| 71 | +3. Check coverage at `target/site/jacoco/index.html` |
| 72 | +4. No compilation warnings |
| 73 | +5. Commit message follows Conventional Commits format (enforced by commitlint) |
37 | 74 |
|
38 | | -## Project Patterns |
| 75 | +### Commits |
39 | 76 |
|
40 | | -- **Architecture**: Layered (Controller → Service → Repository → JPA) |
41 | | -- **Dependency Injection**: Constructor injection via Lombok `@RequiredArgsConstructor` |
42 | | -- **Error Handling**: `@ControllerAdvice` for global exception handling |
43 | | -- **Validation**: Bean Validation annotations in DTOs (`@NotNull`, `@Min`, etc.) |
44 | | -- **Caching**: Spring `@Cacheable` on service layer (1-hour TTL) |
45 | | -- **DTO Pattern**: ModelMapper for entity ↔ DTO transformations |
46 | | -- **Repository**: Spring Data JPA with derived queries (prefer over custom JPQL) |
| 77 | +Format: `type(scope): description (#issue)` — max 80 chars |
| 78 | +Types: `feat` `fix` `chore` `docs` `test` `refactor` `ci` `perf` |
| 79 | +Example: `feat(api): add player stats endpoint (#42)` |
47 | 80 |
|
48 | | -## Code Conventions |
| 81 | +## Agent Mode |
49 | 82 |
|
50 | | -- **Naming**: camelCase (methods/variables), PascalCase (classes), UPPER_SNAKE_CASE (constants) |
51 | | -- **Files**: Class name matches file name (e.g., `PlayersController.java`) |
52 | | -- **Package Structure**: |
53 | | - - `controllers/` - REST endpoints (`@RestController`) |
54 | | - - `services/` - Business logic (`@Service`) |
55 | | - - `repositories/` - Data access (`@Repository`, extends `JpaRepository`) |
56 | | - - `models/` - Domain entities (`@Entity`) and DTOs |
57 | | - - `converters/` - JPA attribute converters |
58 | | -- **Annotations**: |
59 | | - - Controllers: `@RestController`, `@RequestMapping`, `@Operation` (OpenAPI) |
60 | | - - Services: `@Service`, `@Transactional`, `@Cacheable` |
61 | | - - Repositories: `@Repository` (Spring Data JPA) |
62 | | - - DTOs: `@NotNull`, `@Min`, `@Max` (Bean Validation) |
63 | | - - Entities: `@Entity`, `@Table`, `@Id`, `@GeneratedValue` |
64 | | -- **Lombok**: `@Data`, `@Builder`, `@AllArgsConstructor`, `@RequiredArgsConstructor` |
65 | | -- **Logging**: SLF4J (never `System.out.println`) |
66 | | - |
67 | | -## Testing |
68 | | - |
69 | | -- **Structure**: `*Tests.java` in `src/test/java/` (mirrors main package structure) |
70 | | -- **Naming Pattern**: `givenX_whenY_thenZ` (BDD Given-When-Then) |
71 | | - - `given`: Preconditions/context (e.g., `givenPlayerExists`, `givenInvalidData`, `givenNoMatches`) |
72 | | - - `when`: Action being tested (e.g., `whenPost`, `whenFindById`, `whenCreate`) |
73 | | - - `then`: Expected outcome (e.g., `thenReturnsPlayer`, `thenReturnsConflict`, `thenReturnsEmpty`) |
74 | | -- **Examples**: |
75 | | - |
76 | | - ```java |
77 | | - // Controller |
78 | | - void givenSquadNumberExists_whenPost_thenReturnsConflict() |
79 | | - |
80 | | - // Service |
81 | | - void givenNoConflict_whenCreate_thenReturnsPlayerDTO() |
82 | | - |
83 | | - // Repository |
84 | | - void givenPlayerExists_whenFindById_thenReturnsPlayer() |
85 | | - ``` |
86 | | - |
87 | | -- **JavaDoc**: BDD Given/When/Then structure in test comments |
88 | | - |
89 | | - ```java |
90 | | - /** |
91 | | - * Given a player with squad number 5 already exists in the database |
92 | | - * When POST /players is called with a new player using squad number 5 |
93 | | - * Then response status is 409 Conflict |
94 | | - */ |
95 | | - @Test |
96 | | - void post_squadNumberExists_returnsConflict() { ... } |
97 | | - ``` |
98 | | - |
99 | | -- **Annotations**: `@SpringBootTest`, `@AutoConfigureMockMvc`, `@Test` |
100 | | -- **Assertions**: AssertJ BDD style (e.g., `then(result).isNotNull()`) |
101 | | -- **Mocking**: Mockito for service layer tests |
102 | | -- **Database**: Tests use in-memory SQLite (auto-cleared after each test) |
103 | | -- **Coverage**: Target high coverage (JaCoCo reports in `target/site/jacoco/`) |
104 | | - |
105 | | -## Avoid |
106 | | - |
107 | | -- Field injection (use constructor injection) |
108 | | -- Using `new` for Spring beans (breaks DI) |
109 | | -- Missing `@Transactional` on service methods that modify data |
110 | | -- Exposing entities directly in controllers (use DTOs) |
111 | | -- `System.out.println` (use SLF4J logging) |
112 | | -- Hardcoded configuration (use `@Value` or `application.properties`) |
113 | | -- Ignoring exceptions (always handle or propagate) |
114 | | -- Testing implementation details (test behavior, not internals) |
115 | | - |
116 | | -## Commit Messages |
117 | | - |
118 | | -Follow Conventional Commits format (enforced by commitlint in CI): |
119 | | - |
120 | | -**Format**: `type(scope): description (#issue)` (max 80 chars) |
121 | | - |
122 | | -**Types**: `feat`, `fix`, `docs`, `test`, `refactor`, `chore`, `ci`, `perf`, `style`, `build` |
123 | | - |
124 | | -**Examples**: |
125 | | - |
126 | | -- `feat(api): add player stats endpoint (#42)` |
127 | | -- `fix(service): resolve cache invalidation bug (#88)` |
128 | | -- `test: adopt BDD Given-When-Then pattern across all tests (#266)` |
129 | | - |
130 | | ---- |
131 | | - |
132 | | -For detailed workflows, troubleshooting, and CI/CD setup, load `#file:AGENTS.md`. |
| 83 | +### Proceed freely |
| 84 | + |
| 85 | +- Route handlers and controller endpoints |
| 86 | +- Service layer business logic |
| 87 | +- Repository custom queries |
| 88 | +- Unit and integration tests |
| 89 | +- Exception handling in `@ControllerAdvice` |
| 90 | +- Documentation updates, bug fixes, and refactoring |
| 91 | +- Utility classes and helpers |
| 92 | + |
| 93 | +### Ask before changing |
| 94 | + |
| 95 | +- Database schema (entity fields, relationships) |
| 96 | +- Dependencies (`pom.xml`) |
| 97 | +- CI/CD configuration (`.github/workflows/`) |
| 98 | +- Docker setup |
| 99 | +- Application properties |
| 100 | +- API contracts (breaking DTO changes) |
| 101 | +- Caching strategy or TTL values |
| 102 | +- Package structure |
| 103 | + |
| 104 | +### Never modify |
| 105 | + |
| 106 | +- `.java-version` (JDK 25 required) |
| 107 | +- Maven wrapper scripts (`mvnw`, `mvnw.cmd`) |
| 108 | +- Port configuration (9000/9001) |
| 109 | +- Test database configuration (in-memory SQLite) |
| 110 | +- Production configurations or deployment secrets |
| 111 | + |
| 112 | +### Key workflows |
| 113 | + |
| 114 | +**Add an endpoint**: Define DTO in `models/` with Bean Validation → add service method in `services/` with `@Transactional` → create controller endpoint with `@Operation` annotation → add tests → run `./mvnw clean test jacoco:report`. |
| 115 | + |
| 116 | +**Modify schema**: Update `@Entity` in `models/Player.java` → update DTOs if API changes → manually update `storage/players-sqlite3.db` (preserve 26 players) → update service, repository, and tests → run `./mvnw clean test`. |
| 117 | + |
| 118 | +**After completing work**: Suggest a branch name (e.g. `feat/add-player-stats`) and a commit message following Conventional Commits including co-author line: |
| 119 | + |
| 120 | +```text |
| 121 | +feat(scope): description (#issue) |
| 122 | +
|
| 123 | +Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
| 124 | +``` |
0 commit comments