Spring Boot REST API in Kotlin
Build a REST API with Spring Boot and Kotlin: controllers, services, error handling, and validation.
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.web.bind.annotation.*
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.stereotype.Service
import jakarta.validation.Valid
import jakarta.validation.constraints.*
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicLong
@SpringBootApplication
class Application
fun main(args: Array<String>) { runApplication<Application>(*args) }
// DTOs
data class CreateUserRequest(
@field:NotBlank val name: String,
@field:Email val email: String,
@field:Min(0) @field:Max(150) val age: Int
)
data class UserResponse(
val id: Long,
val name: String,
val email: String,
val age: Int
)
data class ErrorResponse(
val status: Int,
val message: String,
val timestamp: Long = System.currentTimeMillis()
)
// Domain
data class User(val id: Long, val name: String, val email: String, val age: Int)
// Service
@Service
class UserService {
private val users = ConcurrentHashMap<Long, User>()
private val idGen = AtomicLong(0)
fun findAll(): List<User> = users.values.toList()
fun findById(id: Long): User =
users[id] ?: throw NotFoundException("User $id not found")
fun create(request: CreateUserRequest): User {
val user = User(idGen.incrementAndGet(), request.name, request.email, request.age)
users[user.id] = user
return user
}
fun delete(id: Long) {
users.remove(id) ?: throw NotFoundException("User $id not found")
}
}
class NotFoundException(message: String) : RuntimeException(message)
// Controller
@RestController
@RequestMapping("/api/users")
class UserController(private val service: UserService) {
@GetMapping
fun list() = service.findAll().map { it.toResponse() }
@GetMapping("/{id}")
fun get(@PathVariable id: Long) = service.findById(id).toResponse()
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
fun create(@Valid @RequestBody request: CreateUserRequest) =
service.create(request).toResponse()
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
fun delete(@PathVariable id: Long) = service.delete(id)
}
// Extension function for mapping
fun User.toResponse() = UserResponse(id, name, email, age)
// Global error handler
@RestControllerAdvice
class GlobalExceptionHandler {
@ExceptionHandler(NotFoundException::class)
fun handleNotFound(ex: NotFoundException) =
ResponseEntity.status(404).body(ErrorResponse(404, ex.message ?: "Not found"))
@ExceptionHandler(Exception::class)
fun handleGeneral(ex: Exception) =
ResponseEntity.status(500).body(ErrorResponse(500, ex.message ?: "Internal error"))
}Sponsored
Railway
Use Cases
- RESTful API development with Kotlin
- Spring Boot microservices
- CRUD operations with validation
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
Ktor Server Routing and Middleware
Build HTTP APIs with Ktor: routing, content negotiation, authentication, and middleware plugins.
Best for: Building REST APIs with Kotlin-native framework
Spring WebFlux with Kotlin Coroutines
Build reactive Spring APIs using Kotlin coroutines: suspend functions, Flow, and coRouter DSL.
Best for: Non-blocking REST APIs with Kotlin coroutines
Spring Boot REST Controller with CRUD
Create a complete REST API with Spring Boot: GET, POST, PUT, DELETE with validation and error handling.
Best for: Building RESTful APIs with Spring Boot
Spring Boot Global Exception Handler
Centralized error handling with @ControllerAdvice for validation errors, 404s, and custom exceptions.
Best for: Consistent error responses across all endpoints