CLAUDE.md — Java / Spring Boot Project
Project Basics
This is a Java 21+ project using Spring Boot 3.x. Use records for DTOs, sealed interfaces where appropriate, and prefer immutability. All code must compile cleanly with zero warnings.
Package Structure
src/main/java/com/example/— main application code- Group by feature, not by layer:
user/,order/,auth/— each with its own controller, service, repository - Shared utilities in
common/orshared/package - Configuration classes in
config/package - No circular dependencies between feature packages
Naming Conventions
PascalCasefor classes and interfacescamelCasefor methods and variablesUPPER_SNAKE_CASEfor constants- Interfaces don’t need
Iprefix —UserRepositorynotIUserRepository - Implementation suffix only when multiple impls exist:
UserServiceImpl
Dependency Injection
- Constructor injection only — no field injection with
@Autowired - Use
@RequiredArgsConstructor(Lombok) or explicit constructors - Keep constructors small — if you need 5+ dependencies, the class does too much
- Use
@Configurationclasses for bean definitions, not XML
Error Handling
- Use
@ControllerAdvicewith@ExceptionHandlerfor global error handling - Define custom exceptions for domain errors:
UserNotFoundException extends RuntimeException - Return consistent error response format:
{ "error": "...", "code": "...", "details": [...] } - Never expose stack traces in API responses
- Log exceptions at the handler level, not at every catch site
Database & JPA
- Spring Data JPA for repositories — extend
JpaRepositoryorCrudRepository - Use
@Transactionalon service methods, not on repositories - Flyway or Liquibase for database migrations — never modify existing migrations
- N+1 queries: use
@EntityGraphorJOIN FETCHin JPQL - Always define
equals()andhashCode()on entities using business keys, not IDs
Testing
- JUnit 5 + Mockito for unit tests
@SpringBootTestfor integration tests (use sparingly — they’re slow)@WebMvcTestfor controller layer tests@DataJpaTestfor repository layer tests- Use Testcontainers for database integration tests
- Test naming:
shouldReturnUserWhenIdExists()
API Design
- RESTful endpoints:
GET /api/users,POST /api/users,GET /api/users/{id} - Use
@Validon request bodies with Bean Validation annotations - Pagination with
Pageable:GET /api/users?page=0&size=20&sort=name - Return appropriate status codes: 201 for creation, 204 for deletion, 409 for conflicts
- Version APIs in the URL if breaking changes are needed:
/api/v2/users
Build & Deploy
./mvnw clean packageor./gradlew build— use the wrapper, not system Maven/Gradle- Run with adequate memory:
JAVA_OPTS="-Xmx512m"for dev, tune for production - Use Spring profiles:
application-dev.yml,application-prod.yml - Docker: multi-stage build with
eclipse-temurinbase image
Verification
./mvnw compile— compiles without errors or warnings./mvnw test— all tests pass./mvnw spotbugs:checkor./mvnw checkstyle:check— no static analysis warnings (if configured)- Application starts without errors:
./mvnw spring-boot:run
Git & GitHub
- Do not push code or create PRs without explicit permission
- Do not perform destructive or irreversible operations without asking first
- Never commit
application-local.ymlor files containing secrets