Русский
Русский
English
Статистика
Реклама

Документируй это

Всем привет! В данной статье хотел бы рассмотреть инструменты документирования в принципиально разных подходах в разработке REST API, а именно для CodeFirst - инструменты SpringRestDocs (а также его надстройку SpringAutoRestDocs) и для ApiFirst - инструменты экосистемы Swagger(Open-Api).

Дисклеймер: В подробности холивара на тему что же лучше CodeFirst или ApiFirst я вдаваться не будут, а постараюсь продемонстрировать возможную практику документации в обоих вариантах.

CodeFirst плюс SpringAutoRestDocs

Как уже описывали в статье про SpringRestDocs это инструмент достаточно широкого использования, позволяющий генерировать различную документацию (аскедок, хтмл и т.д.) на основе тестов. Пожалуй один из немногих недостатков этого инструмента, является его многословность в тестах, а именно - необходимо описывать каждый параметр, каждое поле и т.д. В свою очередь тесы в SpringAutoRestDocs, используя JSR и Spring аннотации, а также Javadoc, становятся более коротким и немногословными.

Чуть более подробно про SpringAutoRestDocs

SpringAutoRestDocs это надстройка над SpringRestDocs, которая ставит своей целью уменьшение написания кода и документации. Основное преимущество этого иструмента - является меньшее количество написанной документации и большая связаность с рабочим кодом.

Некоторые из фичей инструмента:

  • Автоматическое документирования полей запроса и ответа, хедеров и параметров запроса с использованием Jackson, а также описательной части на основе Javadocs

  • Автоматическое документирование опциональности и ограничения полей по спецификации JSR-303

  • Возможность кастомизации итоговых снипеттов

Подробнее можно почитать в официальной документации.

Для демонстрации возьмем классический Swagger PetStore (с небольшой модернизацией, подробно можно посмотреть спеку в репозитории) и имплементируем несколько методов контроллера (addPet, deletePet, getPetById). В статье будет приведен пример на основе одного метода getPetById

Контроллер:

@RestController@RequiredArgsConstructorpublic class PetController implements PetApi {    private final PetRepository petRepository;        @Override    public ResponseEntity<Pet> getPetById(Long petId) {        return new ResponseEntity<>(petRepository.getPetById(petId), HttpStatus.OK);    }  //и другие имплементированные методы}

Репозиторий является обычным листом с несколькими методами доступа.

Базовые настройки для тестовой автодокументации:

Для начала нам необходимо определить базовый класс для всех тестов, который опишет основные правила нашей автоматической документации. Основное что нам понадобится, это сконфигурированный MockMvc (более подробно можно посмотреть в репозитории):

@Beforevoid setUp() throws Exception {  this.mockMvc = MockMvcBuilders    .webAppContextSetup(context)    .alwaysDo(prepareJackson(objectMapper, new TypeMapping()))    .alwaysDo(commonDocumentation())    .apply(documentationConfiguration(restDocumentation)           .uris().withScheme("http").withHost("localhost").withPort(8080)           .and()           .snippets().withTemplateFormat(TemplateFormats.asciidoctor())           .withDefaults(curlRequest(), httpRequest(), httpResponse(),                         requestFields(), responseFields(), pathParameters(),                         requestParameters(), description(), methodAndPath(),                         section(), links(), embedded(), authorization(DEFAULT_AUTHORIZATION),                         modelAttribute(requestMappingHandlerAdapter.getArgumentResolvers())))    .build()  }protected RestDocumentationResultHandler commonDocumentation(Snippet... snippets) {  return document("rest-auto-documentation/{class-name}/{method-name}", commonResponsePreprocessor(), snippets)  }protected OperationResponsePreprocessor commonResponsePreprocessor() {  return preprocessResponse(replaceBinaryContent(), limitJsonArrayLength(objectMapper), prettyPrint())  }
Чуть более подробно про настройки MockMVC

WebApplicationContext получаем от @SpringBootTest

prepareJackson(objectMapper, new TypeMapping()) позволяет настроить ResultHandler, который подготовит наши pojo для библиотеки документирования

withDefaults(curlRequest(), httpRequest(), и т.д.) набор сниппетов, которые будут сгенерированы

commonDocumentation() описывает директорию, куда в build папке разместятся сгенерированные сниппеты, а также препроцессинг ответа контроллера.

Непосредственно сам тест:

Пример теста более подробно можно посмотреть в репозитории.

@Testvoid getPetTest() {//givendef petId = 1L//whendef resultActions = mockMvc.perform(RestDocumentationRequestBuilders.get("/pet/{petId}", petId).header("Accept", "application/json"))//thenresultActions.andExpect(status().isOk()).andExpect(content().string(objectMapper.writeValueAsString(buildReturnPet())))}

Здесь приведен стандартный MockMvc тест, с ожидаемым статусом и ожидаемым телом ответа.

Итого на выходе:

Набор снипеттов с "главным" сниппетом под названием auto-section.adoc (который содержит информацию из всех остальных, указанных в настройках MockMVC) из которых позже можно собрать общий index.adoc для всех методов API. Готовая структура сниппетов:

Готовые сниппеты документы можно посмотреть в репозитории: сниппеты, html сгенеренный на основе сниппетов.

Также при настройках библиотеки мы можем изменять шаблоны либо добавлять свои сниппеты и SprinAutoRestDocs их распознает и воспроизведет ту функциональность, что вам нужна. Дока кастомизации сниппетов, констрейнтов.

Чуть подробнее про кастомизацию сниппетов и ограничений

Функционал кастомизации в SpringAutoRestDocs базируется на таковом же в SpringRestDocs.

К примеру русификация шапок сниппетов и описание ограничений:

ApiFirst плюс Swagger

Как уже описывалось во множестве статей (пример1, пример2) swagger - это open-source проект, включающий OpenApi Specification и широкий набор инструментов для описания, визуализации и документирования REST api.

Чуть более подробно про Swagger

Swagger состоит из двух основных частей - это OpenApi Specification и Swagger Tools.

  • OpenApi Specification - это спецификация описывающая процесс создания REST контракта для более простого процесса разработки и внедрения API. Спецификация может быть описана в формате YAML и JSON. Описание базового синтаксиса, а также более подробную информацию можно изучить по ссылке.

  • Swagger Tools - это инструменты визуализации, документации и генерации клиентно-серверной части REST api. Состоят из трех основных блоков: Swagger Editor(браузерный эдитор, для более удобного написания контракта с поддержкой валидации ситаксиса), Swagger UI(рендер спецификации в качестве интерактивной документации API), Swagger Codegen(генератор серверно-клиентной части, а также некоторых типов документаций)

Ниже мы рассмотрим мульти-модульный проект со следущей структурой: библиотека со свагер генератором (swagger-library), стартер с swagger-ui(swagger-webjar-ui-starter), приложение которое имплементирует классы библиотеки(spring-auto-rest-docs).

Для демонстрации возможностей Swagger возьмем классический Swagger PetStore из примера SpringAutoRestDocs выше.

Настройки build.gradle для модуля библиотеки:

Для реализации генерации server stub и документации на основе Swagger контракта используем OpenApi Generator.

Чуть более подробно про OpenApi Generator

В модуле используется gradle плюс gradle plugin OpenApi Generator.

Сам плагин дает возможность генерить как серверно-клиентную часть, так и различные форматы документации. Более подробно можно посмотреть в ссылке на репозиторий.

Основная таска для генерации библиотеки и ее настройки:

openApiGenerate {    generatorName = 'spring'    inputSpec = specFile    outputDir = "${project.projectDir}/"    id = "${artifactId}"    groupId = projectPackage    ignoreFileOverride = ignoreFile    apiPackage = "${projectPackage}.rest.api"    invokerPackage = "${projectPackage}.rest.invoker"    modelPackage = "${projectPackage}.rest.model"    configOptions = [            dateLibrary            : 'java8',            hideGenerationTimestamp: 'true',            interfaceOnly          : 'true',            delegatePattern        : 'false',            configPackage          : "${projectPackage}.configuration"    ]}
Чуть более подробно про настройки таски openApiGenerate

Незабываем выполнять генерацию кода до компиляции проекта:

task codegen(dependsOn: ['openApiGenerate', 'copySpecs'])compileJava.dependsOn(codegen)compileJava.mustRunAfter(codegen)

Копируем спеки в ресурсы, чтобы была позже возможность отобразить UI прямо из спек:

task copySpecs(type: Copy) {    from("${project.projectDir}/specs")    into("${project.projectDir}/src/main/resources/META-INF/specs")}

При необходимости также можно сгенерить Asciidoc или Html2.

Swagger-ui стартер:

Стартер добавляет в регистр ресурсов спеки с определенными в дефолтными настройками и webjar swagger-ui с измененным путем до дефолтного контракта.

Rest-docs API:

В самом приложении достаточно имплементировать сгенерированный интерфейс и переопределить настройки UI стартера:

@RestController@RestController@RequiredArgsConstructorpublic class PetController implements PetApi {    private final PetRepository petRepository;        @Override    public ResponseEntity<Pet> getPetById(Long petId) {        return new ResponseEntity<>(petRepository.getPetById(petId), HttpStatus.OK);    }  //и другие имплементированные методы}
swagger:  ui:    indexHandler:      enabled: true      resourceHandler: "/api/**"    apis:      - url: http://localhost:8080/specs/some_swagger.yaml        name: My api

Итого на выходе:

Server stub - готовая библиотека с сущностями и интерфейсом для реализации серверной части API.

Swagger UI - с помощью которого мы получаем наглядную визуализацию API и возможность направлять запросы прямо из UI:

Также примеры Asciidoc или Html2 из самого swagger контракта:

Заключение:

Что дает SpringAutoRestDocs:

  • Возможность хранить документацию как в проекте (к примеру в форме собранного index.html из множества сниппетов), так и в любом другом удобном месте.

  • Документация и модель данных всегда синхронизирована с кодом, так как документация генерируется на основе "зеленых" тестов контроллера.

  • Возможность кастомизации сниппетов и ограничений.

Что дает Swagger:

  • Единый артефакт на всех этапах разработки.

  • Документация и модель данных всегда синхронизирована с кодом, так как код генерируется на основе контракта.

  • Возможность использовать UI, в котором будет вся та же информация, что в контракте с возьможностью направлять запросы.

Какой бы вы не выбрали путь разработки, инструменты выше практически всегда позволят вам содержать актуальную документацию, тесно связанную с рабочим кодом.

Источник: habr.com
К списку статей
Опубликовано: 08.05.2021 12:05:15
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Java

Api

Spring

Spring auto rest docs

Swagger

Documentation

Категории

Последние комментарии

© 2006-2021, personeltest.ru