// Backend development with Kotlin, Spring Boot, REST APIs. Use for backend, api, service, kotlin, rest tags. Provides validation commands, testing patterns, and blocker scenarios.
| 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 |
Domain-specific guidance for backend API development, service implementation, and business logic.
Load this Skill when task has tags:
backend, api, service, kotlin, restspring, spring-boot, controller, repository# 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 JAR
./gradlew build
# Build without tests (for quick syntax check)
./gradlew build -x test
# Local development
./gradlew bootRun
# With specific profile
./gradlew bootRun --args='--spring.profiles.active=dev'
✅ 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)
❌ AVOID mocking repositories in integration tests:
// BAD - Mocking repositories misses SQL errors, constraints
@Mock private lateinit var userRepository: UserRepository
when(userRepository.findById(any())).thenReturn(mockUser)
✅ USE real in-memory database:
// 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
}
❌ Avoid: Write 200 lines code + 15 tests → run all → 12 failures → no idea which code caused which failure
✅ Do:
./gradlew test --tests "ToolTest.shouldHandleBasicCase"Benefits: Feedback in seconds, isolates root cause immediately.
When test fails:
println("Full response: $result")
println("Response keys: ${result.jsonObject.keys}")
❌ BAD - Missing required fields:
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:
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.
Issue: Tests expect column that doesn't exist
SQLSyntaxErrorException: Unknown column 'users.password_hash'
What to try:
If blocked: Report to orchestrator - database task may need reopening
Issue: NPE at runtime in service class
NullPointerException: Cannot invoke method on null object
What to try:
? operator, nullable types)Common causes:
Issue: Integration tests pass locally but fail in CI or for others
What to try:
Issue: Task requirements conflict with existing architecture
Task requires middleware auth but project uses annotation-based security
What to try:
If blocked: Report to orchestrator - may need architectural decision or task revision
Issue: Third-party library has known bug
JWT library v3.2.1 has refresh token bug - expires immediately
What to try:
If blocked: Report to orchestrator - may need to wait for library update or use alternative
⚠️ 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.]
Controller:
@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:
@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:
@Repository
interface UserRepository : JpaRepository<User, UUID> {
fun findByEmail(email: String): User?
}
@RestControllerAdvice
class GlobalExceptionHandler {
@ExceptionHandler(NotFoundException::class)
fun handleNotFound(ex: NotFoundException): ResponseEntity<ErrorResponse> {
return ResponseEntity
.status(HttpStatus.NOT_FOUND)
.body(ErrorResponse(ex.message))
}
@ExceptionHandler(ValidationException::class)
fun handleValidation(ex: ValidationException): ResponseEntity<ErrorResponse> {
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(ErrorResponse(ex.message))
}
}
❌ 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)
When reading task sections, prioritize:
requirements - What API endpoints need to be builttechnical-approach - How to implement (patterns, libraries)implementation - Specific implementation detailstesting-strategy - How to test the implementationFor deeper patterns and examples, see: