Skip to content

Commit 3ca43c7

Browse files
authored
Merge pull request #255 from nanotaboada/feat/optimize-ai-agent-instructions
docs: optimize AI agent instructions for token efficiency
2 parents a2f1350 + 51fdabd commit 3ca43c7

File tree

2 files changed

+413
-259
lines changed

2 files changed

+413
-259
lines changed

.github/copilot-instructions.md

Lines changed: 53 additions & 259 deletions
Original file line numberDiff line numberDiff line change
@@ -1,286 +1,80 @@
1-
# Copilot Instructions for java.samples.spring.boot
1+
# GitHub Copilot Instructions
22

3-
## Project Overview
3+
> **⚡ Token Efficiency Note**: This is a minimal pointer file (~500 tokens, auto-loaded by Copilot).
4+
> For complete operational details, reference: `#file:AGENTS.md` (~2,500 tokens, loaded on-demand)
5+
> For specialized knowledge, use: `#file:SKILLS/<skill-name>/SKILL.md` (loaded on-demand when needed)
46
5-
This is a RESTful Web Service proof-of-concept built with **Spring Boot 4** targeting **JDK 25 (LTS)**. The application demonstrates a clean, layered architecture implementing a CRUD API for managing books. It uses a **SQLite database** for runtime persistence (with a pre-seeded database in Docker) and **H2 in-memory** for fast test execution.
7+
## 🎯 Quick Context
68

7-
**Key URLs:**
9+
**Project**: Spring Boot REST API demonstrating modern Java patterns
10+
**Stack**: Java 25 (LTS) • Spring Boot 4 • JPA/Hibernate • SQLite • Maven • Docker
11+
**Pattern**: Controller → Service → Repository → JPA (layered architecture)
12+
**Philosophy**: Learning-focused PoC emphasizing Spring Boot best practices
813

9-
- API Server: `http://localhost:9000`
10-
- Swagger/OpenAPI Docs: `http://localhost:9000/swagger/index.html`
11-
- Actuator Health: `http://localhost:9001/actuator/health`
14+
## 📐 Core Conventions
1215

13-
## Tech Stack
16+
- **Naming**: camelCase (methods/variables), PascalCase (classes)
17+
- **Annotations**: Use Spring stereotypes (@RestController, @Service, @Repository)
18+
- **Lombok**: Reduce boilerplate (@Data, @Builder, @AllArgsConstructor)
19+
- **Dependency Injection**: Constructor injection (Lombok @RequiredArgsConstructor)
20+
- **Testing**: JUnit 5 + AssertJ for fluent assertions
21+
- **Build**: Use `./mvnw` wrapper, NOT system Maven
1422

15-
### Core Framework & Runtime
16-
17-
- **Java**: JDK 25 (LTS) - use modern Java features where appropriate
18-
- **Spring Boot**: 4.0.0 with modular starter dependencies (WebMVC, Data JPA, Validation, Cache, Actuator)
19-
- **Build Tool**: Maven 3.9+ (use `./mvnw` wrapper, NOT system Maven)
20-
- **Database**: SQLite (runtime) with Xerial JDBC driver; H2 in-memory (test scope only)
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-
- **SQLite JDBC** 3.47.1.0: SQLite database driver (Xerial)
30-
- **Hibernate Community Dialects**: Provides `SQLiteDialect` for JPA/Hibernate
31-
32-
### Testing
33-
34-
- **JUnit 5** (Jupiter): Test framework
35-
- **Mockito**: Mocking framework
36-
- **Spring Boot Test**: `@WebMvcTest`, `@DataJpaTest`, `@AutoConfigureCache`, etc.
37-
- **AssertJ**: Preferred assertion library (use over standard JUnit assertions)
38-
39-
### DevOps & CI/CD
40-
41-
- **Docker**: Multi-stage build with Eclipse Temurin Alpine images and pre-seeded SQLite database
42-
- **Docker Compose**: Local containerized deployment with persistent storage volume
43-
- **GitHub Actions**: CI pipeline with coverage reporting (Codecov, Codacy)
44-
45-
## Project Structure
23+
## 🏗️ Architecture at a Glance
4624

4725
```
48-
src/main/java/ar/com/nanotaboada/java/samples/spring/boot/
49-
├── Application.java # Main entry point, @SpringBootApplication
50-
├── controllers/ # REST endpoints (@RestController)
51-
│ └── BooksController.java
52-
├── services/ # Business logic (@Service, caching)
53-
│ └── BooksService.java
54-
├── repositories/ # Data access (@Repository, Spring Data JPA)
55-
│ └── BooksRepository.java
56-
└── models/ # Domain entities & DTOs
57-
├── Book.java # JPA entity
58-
├── BookDTO.java # Data Transfer Object with validation
59-
└── UnixTimestampConverter.java # JPA converter for LocalDate ↔ Unix timestamp
60-
61-
src/test/java/.../test/
62-
├── controllers/ # Controller tests (@WebMvcTest)
63-
├── services/ # Service layer tests
64-
├── repositories/ # Repository tests (@DataJpaTest)
65-
├── BookFakes.java # Test data factory for Book entities
66-
└── BookDTOFakes.java # Test data factory for BookDTO
67-
68-
src/main/resources/
69-
├── application.properties # Application configuration (SQLite)
70-
└── logback-spring.xml # Logging configuration
71-
72-
src/test/resources/
73-
└── application.properties # Test configuration (H2 in-memory)
74-
75-
scripts/
76-
├── entrypoint.sh # Docker entrypoint (copies seed DB on first run)
77-
└── healthcheck.sh # Docker health check using Actuator
78-
79-
storage/
80-
└── books-sqlite3.db # Pre-seeded SQLite database with sample books
26+
Controller → Service → Repository → JPA → Database
27+
↓ ↓ ↓
28+
Validation Cache Query Methods
8129
```
8230

83-
**Package Naming Convention**: `ar.com.nanotaboada.java.samples.spring.boot.<layer>`
84-
**Test Package Convention**: Add `.test` before layer name (e.g., `...samples.spring.boot.test.controllers`)
85-
86-
## Coding Guidelines
87-
88-
### Architecture & Design Patterns
89-
90-
- **Layered Architecture**: Controller → Service → Repository → Entity
91-
- **DTOs**: Use `BookDTO` for API requests/responses; `Book` entity is internal
92-
- **Dependency Injection**: Use constructor injection (Lombok `@RequiredArgsConstructor` or explicit constructors)
93-
- **Caching**: Service layer uses Spring Cache annotations (`@Cacheable`, `@CachePut`, `@CacheEvict`)
94-
- **Validation**: Use Jakarta Bean Validation annotations on DTOs (`@NotBlank`, `@ISBN`, `@URL`, etc.)
95-
96-
### Java Style
31+
- **Controllers**: REST endpoints with @RestController
32+
- **Services**: Business logic with @Service + caching
33+
- **Repositories**: JpaRepository with derived queries
34+
- **DTOs**: ModelMapper for entity ↔ DTO transformations
35+
- **Cache**: Spring Cache abstraction (1-hour TTL)
9736

98-
- **Lombok**: Prefer `@Data`, `@RequiredArgsConstructor`, `@NoArgsConstructor`, `@AllArgsConstructor` over manual code
99-
- **Streams**: Use Java Streams API for collection processing (see `BooksService.retrieveAll()`)
100-
- **Modern Java**: Leverage JDK 25 features (records, pattern matching, sealed classes, etc.) where beneficial
101-
- **Comments**: Section dividers used in controllers/services (e.g., `/* HTTP POST */`)
37+
## ✅ Copilot Should
10238

103-
### Testing Conventions
39+
- Generate idiomatic Spring Boot code with proper annotations
40+
- Use JPA repository patterns (derived queries, @Query)
41+
- Follow REST conventions with ResponseEntity<T>
42+
- Write tests with @SpringBootTest and MockMvc
43+
- Apply Lombok annotations to reduce boilerplate
44+
- Use ModelMapper for DTO transformations
45+
- Implement proper exception handling with @ControllerAdvice
10446

105-
- **Test Class Naming**: `<ClassName>Tests` (plural, e.g., `BooksControllerTests`)
106-
- **Test Method Naming**: `given<Condition>_when<Action>_then<Expected>` (BDD style)
107-
- **Assertions**: Use AssertJ fluent assertions (`assertThat(...).isEqualTo(...)`)
108-
- **Mocking**: Use `@MockitoBean` for Spring beans (new in Spring Boot 4.0), verify interactions with `verify()`
109-
- **Test Data**: Use fake data factories (`BookFakes`, `BookDTOFakes`) for consistent test data
110-
- **Display Names**: Use `@DisplayName` for readable test descriptions
111-
- **Caching in Tests**: Add `@AutoConfigureCache` to slice tests (`@WebMvcTest`, `@DataJpaTest`) when caching is needed
47+
## 🚫 Copilot Should Avoid
11248

113-
### Coverage Exclusions
49+
- Field injection (use constructor injection)
50+
- Using `new` for services (breaks DI)
51+
- Missing @Transactional on service methods
52+
- Exposing entities directly in controllers (use DTOs)
53+
- System.out.println (use SLF4J logging)
54+
- Hardcoded configuration (use @Value or application.yml)
11455

115-
JaCoCo excludes from coverage (see `pom.xml` and `codecov.yml`):
116-
117-
- `Application.java` (main class)
118-
- `models/**` package (POJOs with Lombok)
119-
- Test files and resources
120-
121-
## Build & Run Commands
122-
123-
### Maven Commands (ALWAYS use wrapper)
56+
## ⚡ Quick Commands
12457

12558
```bash
126-
# Clean and compile
127-
./mvnw clean compile
128-
129-
# Run tests
130-
./mvnw test
131-
132-
# Run tests with coverage
133-
./mvnw verify
134-
135-
# Package application
136-
./mvnw package
137-
138-
# Run application locally
59+
# Run with hot reload
13960
./mvnw spring-boot:run
14061

141-
# Skip tests during build (use sparingly)
142-
./mvnw package -DskipTests
143-
```
144-
145-
**Critical Requirements**:
146-
147-
- **ALWAYS use `./mvnw` wrapper** (Unix/macOS) or `mvnw.cmd` (Windows), NOT `mvn`
148-
- **JDK 25 is REQUIRED**: The project targets JDK 25 (LTS)
149-
- **JAVA_HOME must be set**: Maven wrapper requires JAVA_HOME pointing to JDK 25 installation
150-
151-
### Docker Commands
152-
153-
```bash
154-
# Build image
155-
docker compose build
62+
# Test with coverage
63+
./mvnw clean test jacoco:report
15664

157-
# Start application container
65+
# Docker
15866
docker compose up
15967

160-
# Start in detached mode
161-
docker compose up -d
162-
163-
# Stop and remove containers
164-
docker compose down
165-
166-
# View logs
167-
docker compose logs -f
168-
```
169-
170-
**Exposed Ports**:
171-
172-
- `9000`: Main API server
173-
- `9001`: Actuator management endpoints
174-
175-
**Persistent Storage**:
176-
177-
The Docker container uses a "hold" pattern for the pre-seeded SQLite database:
178-
179-
1. Build stage copies `storage/books-sqlite3.db` to `/app/hold/` in the image
180-
2. On first container run, `entrypoint.sh` copies the database to `/storage/` volume
181-
3. Subsequent runs use the existing database from the volume
182-
4. To reset: `docker compose down -v` removes volumes, next `up` restores seed data
183-
184-
## Common Tasks & Patterns
185-
186-
### Adding a New REST Endpoint
187-
188-
1. Add method to `BooksController` with appropriate HTTP mapping (`@GetMapping`, `@PostMapping`, etc.)
189-
2. Annotate with `@Operation` and `@ApiResponses` for OpenAPI documentation
190-
3. Implement business logic in `BooksService`
191-
4. Add/update repository method if needed
192-
5. Write controller tests using `@WebMvcTest` and `MockMvc`
193-
6. Write service tests with mocked repository
194-
195-
### Adding a New Entity/Resource
196-
197-
1. Create JPA entity in `models/` with `@Entity`, `@Table`, Lombok annotations
198-
2. Create corresponding DTO with validation annotations
199-
3. Create repository interface extending `CrudRepository<Entity, ID>`
200-
4. Create service class with `@Service` and caching annotations
201-
5. Create controller with `@RestController` and OpenAPI annotations
202-
6. Create test data factories (e.g., `EntityFakes.java`)
203-
7. Write comprehensive tests for all layers
204-
205-
### Updating Dependencies
206-
207-
- Dependencies are managed by Dependabot (daily checks)
208-
- Spring Boot dependencies are grouped and ignored for individual updates
209-
- Manually update versions in `pom.xml` `<properties>` section if needed
210-
211-
### Running Coverage Reports
212-
213-
```bash
214-
./mvnw clean verify
215-
# Report available at: target/site/jacoco/index.html
68+
# Swagger: http://localhost:9000/swagger-ui/index.html
69+
# Actuator: http://localhost:9001/actuator/health
21670
```
21771

218-
## Troubleshooting
219-
220-
### Build Failures
221-
222-
- **Lombok not working**: Ensure annotation processor is enabled in IDE and `maven-compiler-plugin` includes Lombok path
223-
- **Tests failing**: Tests use H2 in-memory database via `src/test/resources/application.properties`
224-
- **Port already in use**: Change `server.port` in `application.properties` or kill process using ports 9000/9001
225-
- **JAVA_HOME not set**: Run `export JAVA_HOME=$(/usr/libexec/java_home -v 25)` on macOS or set to JDK 25 path on other systems
226-
- **CacheManager errors in tests**: Add `@AutoConfigureCache` annotation to slice tests (`@WebMvcTest`, `@DataJpaTest`)
227-
- **SQLite file not found**: Ensure `storage/books-sqlite3.db` exists for local development
228-
229-
### Docker Issues
230-
231-
- **Container health check failing**: Verify Actuator is accessible at `http://localhost:9001/actuator/health`
232-
- **Build context too large**: Ensure `.dockerignore` excludes `target/` and `.git/`
233-
- **Database not persisting**: Check that `java-samples-spring-boot_storage` volume exists (`docker volume ls`)
234-
- **Stale seed data**: Run `docker compose down -v` to remove volumes and restore fresh seed data on next `up`
235-
236-
### Common Pitfalls
237-
238-
- **Don't use system Maven**: Always use `./mvnw` wrapper
239-
- **Don't modify `Application.java` coverage**: It's excluded by design
240-
- **Don't test Lombok-generated code**: Focus on business logic
241-
- **Repository interfaces**: Custom query methods may not show in coverage (JaCoCo limitation)
242-
- **Spring Boot 4.0 modular packages**: Test annotations like `@WebMvcTest`, `@DataJpaTest`, and `@AutoConfigureCache` are now in modular packages (e.g., `org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest`)
243-
244-
### SQLite Configuration Notes
245-
246-
- **Date storage**: LocalDate fields are stored as Unix timestamps (INTEGER) for robustness - no parsing issues
247-
- **Converter**: `UnixTimestampConverter` handles LocalDate ↔ epoch seconds conversion via JPA `@Convert`
248-
- **DDL auto**: Use `ddl-auto=none` since the database is pre-seeded (SQLite has limited ALTER TABLE support)
249-
- **Tests use H2**: The converter works seamlessly with both H2 and SQLite databases
250-
251-
## CI/CD Pipeline
252-
253-
### GitHub Actions Workflow (`.github/workflows/maven.yml`)
254-
255-
1. **Verify Job**: Compile, test, generate coverage with `mvn verify`
256-
2. **Coverage Job**: Upload JaCoCo reports to Codecov and Codacy
257-
3. **Container Job**: Build and push Docker image to GitHub Container Registry (on `master` push only)
258-
259-
**Required Secrets**:
260-
261-
- `CODECOV_TOKEN`: Codecov integration token
262-
- `CODACY_PROJECT_TOKEN`: Codacy integration token
263-
- `GITHUB_TOKEN`: Automatically provided for GHCR push
264-
265-
## Contributing
266-
267-
Follow [Conventional Commits](https://www.conventionalcommits.org/):
268-
269-
- `feat:` for new features
270-
- `fix:` for bug fixes
271-
- `chore:` for maintenance tasks
272-
273-
**Commit Style**: Keep commits logical and atomic. Squash checkpoint commits before PR.
274-
275-
**PR Requirements**:
72+
## 📚 Need More Detail?
27673

277-
- All tests must pass
278-
- Coverage should not decrease significantly
279-
- Follow existing code style and patterns
280-
- Update API documentation if endpoints change
74+
**For operational procedures**: Load `#file:AGENTS.md`
75+
**For Docker expertise**: *(Planned)* `#file:SKILLS/docker-containerization/SKILL.md`
76+
**For testing patterns**: *(Planned)* `#file:SKILLS/testing-patterns/SKILL.md`
28177

282-
## Additional Resources
78+
---
28379

284-
- **Code of Conduct**: See `CODE_OF_CONDUCT.md`
285-
- **Detailed Contributing Guide**: See `CONTRIBUTING.md`
286-
- **Project Philosophy**: Small, incremental changes over large rewrites (per Linus Torvalds quote in CONTRIBUTING.md)
80+
💡 **Why this structure?** Copilot auto-loads this file on every chat (~500 tokens). Loading `AGENTS.md` or `SKILLS/` explicitly gives you deep context only when needed, saving 80% of your token budget!

0 commit comments

Comments
 (0)