$npx -y skills add giuseppe-trisciuoglio/developer-kit --skill spring-boot-crud-patternsProvides and generates complete CRUD workflows for Spring Boot 3 services. Creates feature-focused architecture with Spring Data JPA aggregates, repositories, DTOs, controllers, and REST APIs. Validates domain invariants and transaction boundaries. Use when modeling Java backend
| 1 | # Spring Boot CRUD Patterns |
| 2 | |
| 3 | ## Overview |
| 4 | |
| 5 | Provides complete CRUD workflows for Spring Boot 3.5+ services using feature-focused architecture. Creates and validates domain aggregates, JPA repositories, application services, and REST controllers with proper separation of concerns. Defer detailed code listings to reference files for progressive disclosure. |
| 6 | |
| 7 | ## When to Use |
| 8 | |
| 9 | - Create REST endpoints for create/read/update/delete workflows backed by Spring Data JPA. |
| 10 | - Implement feature packages following DDD-inspired architecture with aggregates, repositories, and application services. |
| 11 | - Define DTO records, request validation, and controller mappings for external clients. |
| 12 | - Diagnose CRUD regressions, repository contracts, or transaction boundaries in existing Spring Boot services. |
| 13 | - Trigger phrases: **"implement Spring CRUD controller"**, **"create an endpoint"**, **"add database entity"**, **"refine feature-based repository"**, **"map DTOs for JPA aggregate"**, **"add pagination to REST list endpoint"**. |
| 14 | |
| 15 | ## Instructions |
| 16 | |
| 17 | Follow this streamlined workflow to deliver feature-aligned CRUD services with explicit validation gates: |
| 18 | |
| 19 | ### 1. Establish Feature Structure |
| 20 | Create `feature/<name>/` directories with `domain`, `application`, `presentation`, and `infrastructure` subpackages. |
| 21 | **Validate**: Verify directory structure matches the feature boundary before proceeding. |
| 22 | |
| 23 | ### 2. Define Domain Model |
| 24 | Create entity classes with invariants enforced through factory methods (`create`, `update`). Keep domain logic framework-free. |
| 25 | **Validate**: Assert all invariants are covered by unit tests before advancing. |
| 26 | |
| 27 | ### 3. Expose Domain Ports |
| 28 | Declare repository interfaces in `domain/repository` describing persistence contracts without implementation details. |
| 29 | **Validate**: Confirm interface signatures match domain operations. |
| 30 | |
| 31 | ### 4. Provide Infrastructure Adapter |
| 32 | Create JPA entities in `infrastructure/persistence` that map to domain models. Implement Spring Data repositories. |
| 33 | **Validate**: Run `@DataJpaTest` to verify entity mapping and repository integration. |
| 34 | |
| 35 | ### 5. Implement Application Services |
| 36 | Create `@Transactional` service classes that orchestrate domain operations and DTO mapping. |
| 37 | **Validate**: Ensure transaction boundaries are correct and optimistic locking is applied where needed. |
| 38 | |
| 39 | ### 6. Define DTOs and Controllers |
| 40 | Use Java records for API contracts with `jakarta.validation` annotations. Map REST endpoints with proper status codes. |
| 41 | **Validate**: Test validation constraints and verify HTTP status codes (201 POST, 200 GET, 204 DELETE). |
| 42 | |
| 43 | ### 7. Validate and Deploy |
| 44 | Run integration tests with Testcontainers. Verify migrations (Liquibase/Flyway) mirror the aggregate schema. |
| 45 | **Validate**: Execute full test suite before deployment; confirm schema migration scripts are applied. |
| 46 | |
| 47 | See `references/examples-product-feature.md` for complete code aligned with each step. |
| 48 | |
| 49 | ## Examples |
| 50 | |
| 51 | ### Java Code Example: Product Feature |
| 52 | |
| 53 | ```java |
| 54 | // feature/product/domain/Product.java |
| 55 | package com.example.product.domain; |
| 56 | |
| 57 | import java.math.BigDecimal; |
| 58 | import java.time.Instant; |
| 59 | |
| 60 | public record Product( |
| 61 | String id, |
| 62 | String name, |
| 63 | String description, |
| 64 | BigDecimal price, |
| 65 | int stock, |
| 66 | Instant createdAt, |
| 67 | Instant updatedAt |
| 68 | ) { |
| 69 | public static Product create(String name, String desc, BigDecimal price, int stock) { |
| 70 | if (name == null || name.isBlank()) throw new IllegalArgumentException("Name required"); |
| 71 | if (price == null || price.compareTo(BigDecimal.ZERO) < 0) throw new IllegalArgumentException("Invalid price"); |
| 72 | return new Product(null, name.trim(), desc, price, stock, Instant.now(), null); |
| 73 | } |
| 74 | |
| 75 | public Product withPrice(BigDecimal newPrice) { |
| 76 | return new Product(id, name, description, newPrice, stock, createdAt, Instant.now()); |
| 77 | } |
| 78 | } |
| 79 | ``` |
| 80 | |
| 81 | ```java |
| 82 | // feature/product/domain/repository/ProductRepository.java |
| 83 | package com.example.product.domain.repository; |
| 84 | |
| 85 | import com.example.product.domain.Product; |
| 86 | import java.util.Optional; |
| 87 | |
| 88 | public interface ProductRepository { |
| 89 | Product save(Product product); |
| 90 | Optional<Product> findById(String id); |
| 91 | void deleteById(String id); |
| 92 | } |
| 93 | ``` |
| 94 | |
| 95 | ```java |
| 96 | // feature/product/infrastructure/persistence/ProductJpaEntity.java |
| 97 | package com.example.product.infrastructure.persistence; |
| 98 | |
| 99 | import jakarta.persistence.*; |
| 100 | import java.math.BigDecimal; |
| 101 | import java.time.Instant; |
| 102 | |
| 103 | @Entity @Table(name = "products") |
| 104 | public class ProductJpaEntity { |
| 105 | @Id @GeneratedValue(strategy = GenerationType.UUID) |