--- name: Backend Implementation description: Backend development with Kotlin, Spring Boot, REST APIs. Use for backend, api, service, kotlin, rest tags. Provides validation commands, testing patterns, and blocker scenarios. allowed-tools: Read, Write, Edit, Bash, Grep, Glob --- # Backend Implementation Skill Domain-specific guidance for backend API development, service implementation, and business logic. ## When To Use This Skill Load this Skill when task has tags: - `backend`, `api`, `service`, `kotlin`, `rest` - `spring`, `spring-boot`, `controller`, `repository` ## Validation Commands ### Run Tests ```bash # Full test suite ./gradlew test # Specific test class ./gradlew test --tests "UserServiceTest" # Single test method ./gradlew test --tests "UserServiceTest.shouldCreateUser" # With build ./gradlew clean test ``` ### Build Project ```bash # Build JAR ./gradlew build # Build without tests (for quick syntax check) ./gradlew build -x test ``` ### Run Application ```bash # Local development ./gradlew bootRun # With specific profile ./gradlew bootRun --args='--spring.profiles.active=dev' ``` ## Success Criteria (Before Completing Task) ✅ **ALL tests MUST pass** (0 failures, 0 errors) ✅ **Build MUST succeed** without compilation errors ✅ **Code follows project conventions** (existing patterns) ✅ **API endpoints tested** (integration tests) ✅ **Error handling implemented** (try-catch, validation) ## Common Backend Tasks ### REST API Endpoints - Controller with request mapping - Request/response DTOs - Service layer business logic - Repository integration - Error handling (400, 401, 404, 500) - Validation (@Valid annotations) ### Service Implementation - Business logic in service classes - Transaction management (@Transactional) - Error handling and exceptions - Dependency injection (@Autowired, constructor injection) ### Database Integration - Repository interfaces (JPA, Exposed ORM) - Entity mapping - Query methods - Transaction boundaries ## Testing Principles for Backend ### Use Real Infrastructure for Integration Tests ❌ **AVOID mocking repositories in integration tests:** ```kotlin // BAD - Mocking repositories misses SQL errors, constraints @Mock private lateinit var userRepository: UserRepository when(userRepository.findById(any())).thenReturn(mockUser) ``` ✅ **USE real in-memory database:** ```kotlin // GOOD - Tests actual integration @SpringBootTest @Transactional // Auto-rollback after each test class UserApiTest { @Autowired private lateinit var userRepository: UserRepository @Autowired private lateinit var userService: UserService // Tests real database, serialization, constraints } ``` ### Test Incrementally, Not in Batches ❌ **Avoid:** Write 200 lines code + 15 tests → run all → 12 failures → no idea which code caused which failure ✅ **Do:** 1. Write basic implementation 2. Write ONE happy path test 3. Run ONLY that test: `./gradlew test --tests "ToolTest.shouldHandleBasicCase"` 4. Fix until passes 5. Add ONE edge case test 6. Run ONLY that test 7. Repeat **Benefits:** Feedback in seconds, isolates root cause immediately. ### Debug with Actual Output When test fails: 1. **Read error message carefully** - tells you what's wrong 2. **Print actual output:** ```kotlin println("Full response: $result") println("Response keys: ${result.jsonObject.keys}") ``` 3. **Verify assumptions about test data** - count manually 4. **Fix root cause, not symptoms** ### Create Complete Test Entities ❌ **BAD - Missing required fields:** ```kotlin val task = Task( id = UUID.randomUUID(), title = "Test Task", status = TaskStatus.PENDING // Missing: summary, priority, complexity, timestamps ) taskRepository.create(task) // FAILS: NOT NULL constraint ``` ✅ **GOOD - Complete entity:** ```kotlin val task = Task( id = UUID.randomUUID(), title = "Test Task", summary = "Test summary", // Required status = TaskStatus.PENDING, // Required priority = Priority.HIGH, // Required complexity = 5, // Required tags = listOf("test"), projectId = testProjectId, createdAt = Instant.now(), // Required modifiedAt = Instant.now() // Required ) ``` **How to find required fields:** Check migration SQL or ORM model definition. ## Common Blocker Scenarios ### Blocker 1: Missing Database Schema **Issue:** Tests expect column that doesn't exist ``` SQLSyntaxErrorException: Unknown column 'users.password_hash' ``` **What to try:** - Check migration files - is column defined? - Review prerequisite database tasks - marked complete but incomplete? - Check if column was renamed **If blocked:** Report to orchestrator - database task may need reopening ### Blocker 2: NullPointerException in Service **Issue:** NPE at runtime in service class ``` NullPointerException: Cannot invoke method on null object ``` **What to try:** - Check dependency injection - is @Autowired present? - Check constructor injection - all parameters provided? - Check @Configuration on config class - Check @Service or @Component on service class - Add null safety (Kotlin: use `?` operator, nullable types) **Common causes:** - Missing @Configuration annotation - Spring not scanning package - Circular dependency ### Blocker 3: Integration Test Failures **Issue:** Integration tests pass locally but fail in CI or for others **What to try:** - Check test isolation - are tests cleaning up state? - Check @Transactional with rollback - Check test order dependencies (tests should be independent) - Check H2/in-memory DB configuration matches production DB type - Check test data initialization ### Blocker 4: Architectural Conflict **Issue:** Task requirements conflict with existing architecture ``` Task requires middleware auth but project uses annotation-based security ``` **What to try:** - Review existing patterns in codebase - Check architecture documentation - Look for similar implementations **If blocked:** Report to orchestrator - may need architectural decision or task revision ### Blocker 5: External Dependency Bug **Issue:** Third-party library has known bug ``` JWT library v3.2.1 has refresh token bug - expires immediately ``` **What to try:** - Check library changelog - is fix available in newer version? - Search for known issues in library's issue tracker - Try workaround if documented **If blocked:** Report to orchestrator - may need to wait for library update or use alternative ## Blocker Report Format ``` ⚠️ BLOCKED - Requires Senior Engineer Issue: [Specific problem - NPE at UserService.kt:42, missing column, etc.] Attempted Fixes: - [What you tried #1] - [What you tried #2] - [Why attempts didn't work] Root Cause (if known): [Your analysis] Partial Progress: [What work you DID complete] Context for Senior Engineer: - Error output: [Paste error] - Test results: [Test failures] - Related files: [Files involved] Requires: [What needs to happen - Senior Engineer investigation, etc.] ``` ## Quick Reference ### Spring Boot Patterns **Controller:** ```kotlin @RestController @RequestMapping("/api/users") class UserController(private val userService: UserService) { @PostMapping fun createUser(@Valid @RequestBody request: CreateUserRequest): User { return userService.createUser(request) } @GetMapping("/{id}") fun getUser(@PathVariable id: UUID): User { return userService.findById(id) ?: throw NotFoundException("User not found") } } ``` **Service:** ```kotlin @Service @Transactional class UserService( private val userRepository: UserRepository, private val passwordEncoder: PasswordEncoder ) { fun createUser(request: CreateUserRequest): User { val user = User( email = request.email, passwordHash = passwordEncoder.encode(request.password) ) return userRepository.save(user) } } ``` **Repository:** ```kotlin @Repository interface UserRepository : JpaRepository { fun findByEmail(email: String): User? } ``` ### Error Handling ```kotlin @RestControllerAdvice class GlobalExceptionHandler { @ExceptionHandler(NotFoundException::class) fun handleNotFound(ex: NotFoundException): ResponseEntity { return ResponseEntity .status(HttpStatus.NOT_FOUND) .body(ErrorResponse(ex.message)) } @ExceptionHandler(ValidationException::class) fun handleValidation(ex: ValidationException): ResponseEntity { return ResponseEntity .status(HttpStatus.BAD_REQUEST) .body(ErrorResponse(ex.message)) } } ``` ## Common Patterns to Follow 1. **Controller → Service → Repository** layering 2. **Constructor injection** over field injection 3. **@Transactional on service layer** for database operations 4. **DTO pattern** for request/response (don't expose entities) 5. **Exception handling** with @RestControllerAdvice 6. **Validation** with @Valid and constraint annotations 7. **Testing with real database** for integration tests ## What NOT to Do ❌ Don't mock repositories in integration tests ❌ Don't skip tests and mark task complete ❌ Don't expose entities directly in API responses ❌ Don't put business logic in controllers ❌ Don't forget @Transactional for database operations ❌ Don't hardcode configuration (use application.yml) ## Focus Areas When reading task sections, prioritize: - `requirements` - What API endpoints need to be built - `technical-approach` - How to implement (patterns, libraries) - `implementation` - Specific implementation details - `testing-strategy` - How to test the implementation ## Remember - **Run tests incrementally** - one test at a time for fast feedback - **Use real infrastructure** - in-memory database for integration tests - **Debug with actual output** - print what you got, don't assume - **Report blockers promptly** - don't wait, communicate to orchestrator - **Follow existing patterns** - check codebase for similar implementations - **Complete test entities** - all required fields must be populated - **Validation is mandatory** - ALL tests must pass before completion ## Additional Resources For deeper patterns and examples, see: - **PATTERNS.md** - Spring Security, REST API design patterns (load if needed) - **BLOCKERS.md** - Detailed blocker scenarios with solutions (load if stuck) - **examples.md** - Complete working examples (load if uncertain)