En esta página se describirá cómo configurar las aplicaciones Spring-Boot para generar la documentación usada en api.um.es

Para realizar esta documentación se utilizará la librería SpringDoc que implementa el estándar OpenApi/Swagger.

Tabla de contenidos:

1. Configuración


Cambios a realizar:

 1.1 pom.xml

Añadir la versión y las dependencias:

<properties>
...
<springdoc.version>1.6.6</springdoc.version>
...
</properties

<!-- API DOC -->
<dependency>
	<groupId>org.springdoc</groupId>
	<artifactId>springdoc-openapi-webmvc-core</artifactId>
	<version>${springdoc.version}</version>
</dependency>

<dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-hateoas</artifactId>
      <version>${springdoc.version}</version>
</dependency>

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-data-rest</artifactId>
    <version>${springdoc.version}</version>
</dependency>

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-security</artifactId>
    <version>${springdoc.version}</version>
</dependency>


NO SUBIR A GITLAB NUNCA, BAJO NINGÚN CONCEPTO, EL POM.XML CON LA DEPENDENCIA:

<groupId>
org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>


1.2. application.properties

Estas 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
Preguntar a MNCS ante cualquier duda.


# SpringDoc OpenAPI Documentation
springdoc.api-docs.path=/api-docs
# Propiedades inventadas para reubicar las peticiones
springdoc.server.url=https://apidesa.um.es
springdoc.server.path=/${app.author}/${app.apiname}
springdoc.security.issuer-uri=${cas.url}/cas/oidc 


Las propiedades:

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, SpringDoc/Swagger ofrece varias anotaciones, tanto a nivel de clase como de método:

2.1 Anotaciones de clase


@OpenAPIDefinition (
    info = @Info(title = "TITULO DE LA APLICACIÓN", version = "${server.image:1.0}", description = "DESCRIPCIÓN DEL API."), servers = {
	@Server( url = "${springdoc.server.url}" )
} )
@SecurityScheme(	name = "OIDC",
					type = SecuritySchemeType.OPENIDCONNECT,
					openIdConnectUrl = "${springdoc.security.issuer-uri}/.well-known/openid-configuration" )

            De este código, modificar únicamente los atributos:

2.2 Anotaciones de método


 @Operation(summary = "TITULO DEL ENDPOINT", 
            description = "DESCRIPCION DEL ENDPOINT.",
            tags = {""}, //TAG PARA AGRUPAR EN LA DOCUMENTACIÓN
            security = {@SecurityRequirement( name = "OIDC", scopes = "openid" )}, //SOLO SI EL SERVICIO ES PRIVADO 
            responses = { 
                 @ApiResponse(responseCode = "500", description="", content = @Content), 
                 @ApiResponse(responseCode = "200", 
                            description="DESCRIPCION DE LA RESPUESTA SEGÚN EL CÓDIGO DEVUELTO",
                            content= @Content(schema=@Schema(implementation=ClaseDTODevuelto.class))) 
                .... 
            })

De este código los atributos a configurar serían:

Se recomienda que los servicios controlen y devuelvan un conjunto de respuestas completos, según las posibles casuísticas de éxito y error. Ver => Manejo de Errores en FundeWebJS.

¡¡Documentar solo los casos programados!! 


Para realizar una documentación completa es aconsejable documentar también el modelo de datos usado, es decir, los DTO que se emplean en los servicios.
Para documentar los DTO se utiliza la anotación @Schema ( io.swagger.v3.oas.annotations.media.Schema).

Esta notación admite muchos atributos (https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#schemaObject), pero se recomienda usar al menos "description" y "example".

Si se utilizan anotaciones en el DTO correspondientes al estándar Bean Validation, para que los objetos de entrada se validen automáticamente en las peticiones, no es necesario establecer también los atributos de Schema correspondientes.
SpringDoc, con las dependencias maven propuestas, interpreta las anotaciones de Bean Validation y genera la documentación conforme a ellas.
En el siguiente ejemplo se puede ver en las anotaciones @NotBlank y @Size.


Ejemplo: PuebloDTO.java:

@Schema( description = "DTO correspondiente a la tabla Pueblos" )
public class PuebloDTO {

	@Schema( description = "Campo PUE_CODIGO", example = "31104" )
	@NotBlank  //NOTACIÓN BEAN VALIDATION
	@Size( min = 5, max = 5 ) //NOTACIÓN BEAN VALIDATION
	private Integer id;

	@Schema( description = "Campo PUE_NOMBRE", example = "MURCIA", required = true ) //Se puede poner required a nivel de documentación, pero es más funcional usar @NotBlank
	private String nombre;

	@Schema( description = "Municipio donde se localiza el pueblo", example = "30 - MURCIA" )
	private PueMunicipioDTO municipio;

	@Schema( description = "Provincia donde se localiza el municipio", example = "30 - MURCIA" )
	private PueProvinciaDTO provincia;

	@Schema( description = "C.A. donde se localiza la provincia/municipio", example = "14 - REGION DE MURCIA" )
	private PueComunidadAutonomaDTO comunidadAutonoma;
......


Resultado :




F.A.Q.s


Aunque se devuelva un ResponseEntity<T>, hay que establecer el content con nuestro DTO, nunca con ResponseEntity.class.


Si nuestro servicio devuelve una lista, hay que establecer la notación content de la siguiente forma:

@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(


Cuando se documentan los códigos de error devueltos por nuestro servicio, si no estamos devolviendo un objeto creado por nosotros, no es necesario establecer el content para los códigos de error.
Dejar el content vacío, y que no se documente el tipo devuelto, se puede realizar de dos formas:

@ApiResponse(	responseCode = "401", description = "Acceso no autorizado",
				content = @Content( schema = @Schema( hidden = true ) ) ),   // FORMA 1
@ApiResponse(	responseCode = "404", description = "Recurso no encontrado",
				content = @Content )                                         // FORMA 2


Solo debe haber un OpenApiDefinition por aplicación. 

Se puede establecer como anotación del RestController si solo tenemos una clase, pero si tenemos varias, 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.

Ejemplo:

@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 {



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:

@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 )


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.


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).

@Hidden
@GetMapping( PUBLIC_PREFIX + API_VERSION + "/healthz" )
public ResponseEntity<String> getLifeness() {
	return ResponseEntity.ok( "UP");
}


-


Referencias



Artículos Relacionados

Aquí aparecen artículos relacionados sobre la base de las etiquetas que usted seleccione. Haga clic para editar la macro y añadir o modificar las etiquetas.



Incidencias similares