| Estado | ||||
|---|---|---|---|---|
|
En esta página se describirá cómo configurar las aplicaciones Spring-Boot para generar la documentación usada en api.um.es
...
| Tabla de contenidos |
|---|
1. Configuración
Cambios a realizar:
1.1 pom.xml
| Info |
|---|
Con la configuración actual de las APIs, con el parent fundewebjs-api-parent (ver Creación y estructura de proyecto SpringBoot o Migración de APIs a Parent FundeWebJS ), no es necesario realizar ninguna configuración de librerías en pom.xml. |
| Expandir | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| |||||||||||||||
1.1 pom.xmlAñadir la versión y las dependencias:
1.2. application.propertiesEstas variables se incluyen para la configuración local, por si se quisiera realizar alguna comprobación levantando swagger-ui, pero ya estará configurada en los entornos. NO HACE FALTA PARA LOS ENTORNOS.
Deben estar declaradas previamente siguiendo la página de confluence: Migración del backend a soporte oAuth. |
...
2. Documentar servicios
Para documentar correctamente nuestros servicios, OpenAPISpringDoc/Swagger ofrecen ofrece varias anotaciones, tanto a nivel de clase como de método:
...
- title => Título que se mostrará en la documentación. Si tenemos varias clases según los recursos (como debería ser), mencionar en este title el recurso con el que se trabaja en la clase.
P.Ej.: "Consulta de Expediente Académico", "Consulta de Datos de Afiliación", "Solicitudes de Matrícula". description => Descripción larga genérica de los endpoints expuestos en la clase.version => Versión de la documentación. Dejar exactamente el valor del código (version = "${server.image:1.0}").
Info Solo debe haber un OpenApiDefinition por aplicación.
Si nuestra aplicaciónInfo Solo debe haber un OpenApiDefinition por aplicación.
Si nuestra aplicación cuenta con varios RestControllers (por que expone varios recursos), hay que poner la anotación @OpenApiDefinition en la clase Application principal de nuestro proyecto (la que está anotada con @SpringBootApplication).
...
- summary => Título, resumen descriptivo del endpoint.
- description => Descripción larga del endpoint.
- tags => Listado de tags para agrupar endpoints en la documentación. Se puede recomienda agrupar por "Private" o "Public", por recurso, por versiones...al gusto del desarrollador pero manteniendo el mismo criterio en la aplicación.los endpoints por el recurso expuesto.
- security security => Añadir si el servicio es privado.
- responses => Listado de códigos de respuesta devueltos por el endpoint, agrupados en notaciones ApiResponse.
Rellenar, según el caso:- responseCode => código de respuesta http
- description => descripción de la casuística cuando se devuelve el código de respuesta
- content => clase devuelta cuando sucede la respuesta, por ejemplo, un DTO devuelto. (No incluir en caso de error o desconocimiento, es opcional).
...
| Bloque de código |
|---|
@ApiResponse( responseCode = "200",
description = "Listado de mis recursos genéricos",
content = {
@Content( mediaType = "application/json",
array = @ArraySchema( schema = @Schema( implementation = MiRecursoDTO.class ) ) )
} )
@GetMapping( value = PRIVATE_PREFIX + "/v1/misrecursos/", produces = "application/json" )
public ResponseEntity<List<MiRecursoDTO>> getMisRecursos( |
...
Solo debe haber un OpenApiDefinition por aplicación.
Se puede establecer como anotación del RestController si solo se tiene tenemos una clase, pero si tenemos varias clases, la notación OpenApiDefinition debe establecerse en la clase Application de nuestro proyecto (la que está anotada con @SpringBootApplication).
El título y la descripción deben ser relativos a la aplicación completa.
- En los métodos privados, me documenta el JWT o la cabecera Authorization y no puedo probar el endpoint desde la documentación.
Cuando se establece un parámetro para securizar nuestro servicio, ya sea un AuthenticationPrincipal o una cabecera, es necesario ponerle la anotación Parameter( hidden= true) para que este parámetro no se documente.
Ejemplo:
| Bloque de código |
|---|
@GetMapping( PRIVATE_PREFIX + "/v1/misrecursos" )
public ResponseEntity<List<miRecursoDTO>> getMisRecursos(
@Parameter( hidden = true ) @RequestHeader( value = AUTHORIZATION_HEADER, required = true ) String cabecera,
@Parameter( hidden = true ) @AuthenticationPrincipal Jwt jwt )
|
| Info |
|---|
Si se ha incluido la dependencia <artifactId>springdoc-openapi-security</artifactId> en nuestro pom.xml, no es necesario poner a hidden el parámetro AuthenticationPrincipal. |
A parte de ocultar parámetros, ¿se pueden ocultar servicios que no interese documentar?
Sí, además de la FAQ anterior para ocultar parámetros, se pueden ocultar servicios (y clases RestController completas) poniendo la anotación @Hidden (io.swagger.v3.oas.annotations.Hidden).
...
| language | java |
|---|
...
Ejemplo:
| Bloque de código | ||||
|---|---|---|---|---|
| ||||
@OpenAPIDefinition( info = @Info( title = "Servicios RRHH",
version = "${server.image:1.0}",
description = "API REST de Recursos Humanos" ),
servers = {
@Server( url = "${springdoc.server.url}" )
} )
@SecurityScheme( name = "OIDC",
type = SecuritySchemeType.OPENIDCONNECT,
openIdConnectUrl = "${springdoc.security.issuer-uri}/.well-known/openid-configuration" )
@SpringBootApplication( scanBasePackages = {
"es.um.atica.serviciosrrhhapi", "es.um.atica.fundewebjs"
} )
public class ServiciosrrhhApiApplication { |
- En los métodos privados, me documenta el JWT o la cabecera Authorization y no puedo probar el endpoint desde la documentación.
Cuando se establece un parámetro para securizar nuestro servicio, ya sea un AuthenticationPrincipal o una cabecera, es necesario ponerle la anotación Parameter( hidden= true) para que este parámetro no se documente.
Ejemplo:
| Bloque de código |
|---|
@GetMapping( PRIVATE_PREFIX + "/v1/misrecursos" )
public ResponseEntity<List<miRecursoDTO>> getMisRecursos(
@Parameter( hidden = true ) @RequestHeader( value = AUTHORIZATION_HEADER, required = true ) String cabecera,
@Parameter( hidden = true ) @AuthenticationPrincipal Jwt jwt )
|
| Info |
|---|
Si se ha incluido la dependencia <artifactId>springdoc-openapi-security</artifactId> en nuestro pom.xml, no es necesario poner a hidden el parámetro AuthenticationPrincipal. |
A parte de ocultar parámetros, ¿se pueden ocultar servicios que no interese documentar?
Sí, además de la FAQ anterior para ocultar parámetros, se pueden ocultar servicios (y clases RestController completas) poniendo la anotación @Hidden (io.swagger.v3.oas.annotations.Hidden).
| Bloque de código | ||
|---|---|---|
| ||
@Hidden
@GetMapping( PUBLIC_PREFIX + API_VERSION + "/healthz" )
public ResponseEntity<String> getLifeness() {
return ResponseEntity.ok( "UP");
} |
Estoy usando paginación con HATEOAS y Data Rest mediante el parámetro Pageable, ¿cómo lo documento?
Si tenemos un endpoint paginado usando un parámetro @Pageable pageable, es posible que genere la documentación pidiendo como parámetro obligatorio un json con los campos page, size y order y las peticiones que realicemos desde Swagger no funcionen correctamente.
Para solucionar esto, hay que tener en cuenta las siguientes configuraciones:
- Tener la versión de Sprindoc actualizada (1.6.6 a fecha de redacción de esta F.A.Q.)
- Comprobar que están incluidas en el pom.xml las dependencias springdoc-openapi-data-rest y springdoc-openapi-data-hateoas (ver 1.1 de esta misma página)
- Anotar el parámetro @Pageable con la notación @ParameterObject (org.springdoc.api.annotations.ParameterObject)
Ejemplo:
| Bloque de código | ||
|---|---|---|
| ||
@GetMapping( "/misdtos" )
public ResponseEntity<PagedModel<MiDTORepresentationModel>> misdtos(@ParameterObject @PageableDefault( size = 50) Pageable pageable) { |
¿Cómo puedo ver en local la documentación OpenAPI?
Para poder ver, en mi entorno local, cómo quedaría mi documentación OpenApi, no necesito añadir ninguna dependencia extra para levantar un frontal web que la lea. Por defecto, en las aplicaciones FundewebJS, el JSON que representa la documentación OpenAPI se encuentra en http://localhost:8080/api-docs.
Por tanto lo que tenemos que hacer es, acceder a esa URL y copiar el JSON resultante. Una vez copiado nos vamos a Swagger.io https://editor-next.swagger.io/ y pegamos en la parte izquierda nuestro JSON (deberemos quitar todos los comentarios "//" ya que de lo contrario no leerá bien el formato).
Una vez pegado, en la parte de la derecha veremos nuestra documentación en formato web.
...
Referencias
- Documentación SpringDoc OpenApi: https://springdoc.org/#Introduction
- Notaciones Swagger: https://github.com/swagger-api/swagger-core/wiki/AnnotationsSwagger-1.52.X---Annotations
- Baeldung SpringDoc OpenApi: https://www.baeldung.com/spring-rest-openapi-documentation
- Set List of Objects in Swagger API Response: https://www.baeldung.com/java-swagger-set-list-response
...
