Versiones comparadas

Clave

  • Se ha añadido esta línea.
  • Se ha eliminado esta línea.
  • El formato se ha cambiado.

Estado
colourGreen
titleVersión 1.0

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 :

Tabla de contenidos

1. Configuración


Info

Con la configuración actual de las APIs, con el parent fundewebjs-api-parent (ver  Creación y estructura de proyecto SpringBoot Migración de APIs a Parent FundeWebJS ),

no es necesario realizar ninguna configuración de librerías en pom.xml.


Expandir
titleVer configuración antigua.


Cambios a realizar:

 1.1 pom.xml

Añadir la versión y las dependencias:

Bloque de código
languagexml
<properties>
...
<springdoc.version>1.6.12</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>


Advertencia

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

EN CONSTRUCCIÓN 

Guía detallada

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.


Bloque de código
languagejson
# 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:

  • app.author
  • app.apiname
  • cas.url

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


Bloque de código
languagejava
@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 :

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



    Info

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


2.2 Anotaciones de método


Bloque de código
languagejava
 @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 :

  • 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 recomienda agrupar los endpoints por el recurso expuesto.  
  • 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).

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.

Advertencia

¡¡Documentar solo los casos programados!! 


  • 2.3 Documentar el modelo

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

Info

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:

Bloque de código
languagejava
@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 :

Image Added



...

F.A.Q.s

  • Mi servicio devuelve un ResponseEntity<miDTO>, ¿qué pongo en content?.


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


  • Y si mi servicio devuelven una lista de DTOS con ResponseEntity<List<miDTO>>, ¿cómo lo documento?.

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

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(


  • Para documentar respuestas de error con códigos de error (40X, 50X...), ¿qué content pongo?

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:

Bloque de código
@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


  • Tengo varias clases con servicios, agrupados por recursos, pero solo me sale la cabecera con el título y la descripción de una de las clases.

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:

Bloque de código
languagejava
collapsetrue
@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
languagejava
@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
languagejava
@GetMapping( "/misdtos" )
public ResponseEntity<PagedModel<MiDTORepresentationModel>> misdtos(@ParameterObject @PageableDefault( size = 50) Pageable pageable) {

Image Added


  • ¿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


...


Artículos Relacionados

Contenido por etiqueta
showLabelsfalse
max5
spacesMDUYADA
showSpacefalse
sortmodified
reversetrue
typepage
cqllabel = "kb-how-to-article" and type = "page" and space = "MDUYADA"
labelskb-how-to-article

...

Propiedades de página
hiddentrue


Incidencias similares