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

3.5 KiB

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

# Build
mvn clean compile

# Run tests
mvn test

# Run single test class
mvn test -Dtest=UserServiceTest

# Start the app
mvn spring-boot:run