directlx-claude-config/plans/iridescent-giggling-leaf.md

96 lines
3.5 KiB
Markdown

# Plan: Scaffold Spring Boot Project + UserService
## Context
New empty project directory. User wants a full Spring Boot project scaffolded, then a `UserService` added following the same pattern as `ProductService`. The prompt referenced Spring Boot 4, which is not yet released — Spring Boot **3.4.x** (latest stable, supports Java 21 and virtual threads) will be used instead.
## Project Layout
```
/home/directlx/claude-src/cluade-user/
├── pom.xml
├── CLAUDE.md
└── src/
├── main/
│ ├── java/com/example/app/
│ │ ├── AppApplication.java
│ │ ├── exception/
│ │ │ └── ResourceNotFoundException.java
│ │ ├── model/
│ │ │ ├── User.java
│ │ │ └── Product.java
│ │ ├── repository/
│ │ │ ├── UserRepository.java
│ │ │ └── ProductRepository.java
│ │ └── service/
│ │ ├── ProductService.java ← reference pattern
│ │ └── UserService.java ← main deliverable
│ └── resources/
│ └── application.properties
└── test/
└── java/com/example/app/
└── service/
└── UserServiceTest.java
```
## Key Decisions
- **Build**: Maven with `spring-boot-starter-parent` 3.4.2
- **Java**: 21 (records for entities, sealed classes available)
- **DB**: H2 in-memory (dev-ready; swap for PostgreSQL via `application.properties`)
- **Dependencies**: `spring-boot-starter-web`, `spring-boot-starter-data-jpa`, `h2`, `spring-boot-starter-test`
- **Package**: `com.example.app` (conventional; user can rename)
## Files to Create
### `pom.xml`
Spring Boot 3.4.2 parent, Java 21, web + JPA + H2 + test starters.
### `AppApplication.java`
Standard `@SpringBootApplication` entry point.
### `exception/ResourceNotFoundException.java`
`@ResponseStatus(HttpStatus.NOT_FOUND)` extending `RuntimeException` — used by both services for proper error handling.
### `model/Product.java` + `model/User.java`
JPA `@Entity` classes with `@Id @GeneratedValue`. User has: `id`, `name`, `email`, `createdAt`. Product has: `id`, `name`, `price`.
### `repository/ProductRepository.java` + `repository/UserRepository.java`
Extend `JpaRepository<T, Long>`. UserRepository adds `findByEmail(String email)`.
### `service/ProductService.java` (reference pattern)
Constructor-injected `ProductRepository`, `@Service`, methods: `findById`, `findAll`, `create`, `update`, `delete` — throws `ResourceNotFoundException` on missing entity.
### `service/UserService.java` (main deliverable)
Identical pattern to ProductService:
- `@Service` + constructor injection of `UserRepository`
- `findById(Long id)` — throws `ResourceNotFoundException`
- `findAll()` — returns `List<User>`
- `create(User user)` — saves and returns
- `update(Long id, User updated)` — finds, patches fields, saves
- `delete(Long id)` — finds (validates existence), then deletes
### `application.properties`
H2 console enabled, JPA `ddl-auto=create-drop`, show-sql for development.
### `UserServiceTest.java`
Mockito-based unit test (`@ExtendWith(MockitoExtension.class)`) covering findById (found + not-found), findAll, create, update, delete.
### `CLAUDE.md`
Project-specific guidance for future Claude sessions.
## Verification
```bash
# Build
mvn clean compile
# Run tests
mvn test
# Run single test class
mvn test -Dtest=UserServiceTest
# Start the app
mvn spring-boot:run
```