REST-сервис для управления задачами. Проект выполнен на Kotlin, Spring Boot, Reactor и Spring JDBC JdbcClient без ORM/JPA.
Нужна Java 17 или новее.
java -versionЕсли команда не найдена, установите JDK 17 или 21, например Eclipse Temurin:
https://adoptium.net/temurin/releases/
После установки откройте новый терминал и снова проверьте java -version.
Windows:
.\gradlew.bat testLinux / macOS:
./gradlew testWindows:
.\gradlew.bat bootRunLinux / macOS:
./gradlew bootRunПосле запуска сервис доступен по адресу:
http://localhost:8080
Проверить, что сервис отвечает:
GET http://localhost:8080/api/tasks?page=0&size=10
Для Windows PowerShell:
Invoke-RestMethod -Method Get -Uri "http://localhost:8080/api/tasks?page=0&size=10"Windows PowerShell:
$env:SERVER_PORT=8081
.\gradlew.bat bootRunLinux / macOS:
SERVER_PORT=8081 ./gradlew bootRunWindows:
.\gradlew.bat clean buildLinux / macOS:
./gradlew clean buildПосле сборки jar будет находиться в папке:
build/libs/
По умолчанию используется in-memory H2:
spring.datasource.url=jdbc:h2:mem:task_catalog;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSEМиграции Flyway запускаются автоматически при старте приложения. Таблица создается миграцией:
src/main/resources/db/migration/V1__create_tasks_table.sql
Так как база in-memory, данные очищаются после остановки приложения.
POST /api/tasks
Content-Type: application/json
{
"title": "Prepare report",
"description": "Monthly financial report"
}Ответ: 201 Created.
Пример PowerShell:
Invoke-RestMethod `
-Method Post `
-Uri "http://localhost:8080/api/tasks" `
-ContentType "application/json" `
-Body '{"title":"Prepare report","description":"Monthly financial report"}'Пример curl:
curl -i -X POST "http://localhost:8080/api/tasks" \
-H "Content-Type: application/json" \
-d '{"title":"Prepare report","description":"Monthly financial report"}'GET /api/tasks?page=0&size=10&status=NEWПараметры:
page- обязательный, начинается с0.size- обязательный, от1до100.status- необязательный фильтр.
Сортировка: created_at DESC, id DESC.
Ответ:
{
"content": [
{
"id": 1,
"title": "Prepare report",
"description": "Monthly financial report",
"status": "NEW",
"createdAt": "2026-03-26T12:00:00",
"updatedAt": "2026-03-26T12:00:00"
}
],
"page": 0,
"size": 10,
"totalElements": 1,
"totalPages": 1
}GET /api/tasks/1Если задача не найдена, возвращается 404 Not Found.
PATCH /api/tasks/1/status
Content-Type: application/json
{
"status": "DONE"
}Обновляется только поле status. Поле updatedAt меняется автоматически.
Пример PowerShell:
Invoke-RestMethod `
-Method Patch `
-Uri "http://localhost:8080/api/tasks/1/status" `
-ContentType "application/json" `
-Body '{"status":"DONE"}'DELETE /api/tasks/1Ответ: 204 No Content.
NEWIN_PROGRESSDONECANCELLED
Для создания задачи:
titleобязателен.titleне должен быть пустым.- длина
titleдолжна быть от3до100символов.
Для списка задач:
page >= 0.1 <= size <= 100.
Ошибки возвращаются в едином формате:
{
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": {
"title": "title length must be between 3 and 100 characters"
},
"timestamp": "2026-03-26T12:00:00"
}src/main/kotlin/ru/testhhdobr/taskcatalog
├── config
├── controller
├── dto
├── exception
├── model
├── repository
└── service
Слои:
controller- REST API, HTTP-статусы, request validation.service- бизнес-логика и Reactor API.repository- доступ к данным черезJdbcClientи native SQL.dto- request/response модели.model- доменная модельTaskи enumTaskStatus.exception- централизованная обработка ошибок через@RestControllerAdvice.
JdbcClient является блокирующим API, поэтому сервис оборачивает обращения к repository в Mono.fromCallable / Mono.fromRunnable и выполняет их на Schedulers.boundedElastic().
Покрыты основные сценарии:
- service: создание, получение по id, ошибка при отсутствии, обновление статуса, удаление, список с фильтрацией и пагинацией;
- controller: HTTP-статусы, валидация входных данных,
404 Not Found; - repository: интеграционная проверка SQL, маппинга и CRUD на H2.
Запуск:
./gradlew testWindows:
.\gradlew.bat testГотовые HTTP-запросы лежат в файле:
docs/api.http
Их можно запускать из IntelliJ IDEA Ultimate или VS Code с расширением REST Client.
.\gradlew.bat testпроходит без ошибок..\gradlew.bat bootRunзапускает приложение.POST /api/tasksсоздает задачу со статусомNEW.GET /api/tasks?page=0&size=10возвращает страницу задач.GET /api/tasks/{id}возвращает задачу или404.PATCH /api/tasks/{id}/statusменяет только статус иupdatedAt.DELETE /api/tasks/{id}возвращает204 No Content.