Cómo documentar nuestras APIs con Swagger

Luis Cualquiera
3 min readDec 24, 2018

--

Swagger Logo

En múltiples ocasiones, hemos tenido que desarrollar APIs para terceros, las cuales o bien no hemos documentado, o la hemos documentado mal, mediante emails o documentos Word en los que poníamos casi en lenguaje natural la especificación, aunque esta ya hubiera cambiado hace muchas versiones.

El principal problema de documentar las APIs manualmente, es que ésta puede cambiar y se hace engorroso la actualización de esos documentos.

Swagger nos ayuda en esa tarea, aunque sin duda tendremos que poner alo de nuestra parte.

Dadme una API (bien documentada) y moveré el mundo

¿Qué es Swagger?

Swagger nos ofrece una serie de reglas, herramientas y especificaciones que nos ayudan a documentar nuestras APIs.
Añadimos la dependencia maven de springfox-swagger.

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>

Y la de swagger-ui para poder ver la parte visual de Swagger:

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>

Creamos una clase llamada SwaggerConfig con las siguientes anotaciones:

@Configuration
@EnableSwagger2

Y quedaría así:

@Configuration
@EnableSwagger2

public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.any()).paths(PathSelectors.any()).build();
}
}

Una vez arrancado, accedemos a la url:

http://localhost:8080/swagger-ui.html#/

Y vemos esto:

Para ver el fichero JSON generado, podemos acceder a la siguiente URL:

http://localhost:8080/v2/api-docs

Ahora vemos varios Controllers, uno de ellos “basic-error-controller” que no tenemos identificado o anotado:

Como ese no está en nuestro scope, vamos a acotar un poco más el radio de acción de Swagger, para que sólo busque las anotaciones en nuestros paquetes (marcado en negrita):

return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.basePackage(“com.swagger.tutorial.demo”)).paths(PathSelectors.any()).build();

Podemos probar la operación:

Y estas serían las anotaciones (en negrita)

@RestController
@Produces
({ “application/json”, “application/xml” })
public class DemoController {
/**
* Rest controller for application
*/
private static final Logger LOGGER = LoggerFactory.getLogger(DemoController.class);
@GET
@Path(“/isAlive”)
@GetMapping(“/isAlive”)
@ApiOperation(value = “Is Alive operation”, notes = “Return is the microservice is alive with a get operation returning the time”)
@ApiResponses({ @ApiResponse(code = HttpServletResponse.SC_OK, message = “OK”),
@ApiResponse(code = HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message = “INTERNAL ERROR SERVER”),
@ApiResponse(code = HttpServletResponse.SC_UNAUTHORIZED, message = “UNAUTHORIZED”),
@ApiResponse(code = HttpServletResponse.SC_FORBIDDEN, message = “FORBIDDEN”),
@ApiResponse(code = HttpServletResponse.SC_NOT_FOUND, message = “ELEMENTO NOT FOUND”) })
public ResponseEntity<String> isAlive() {
Date tmpDate = new Date();
return new ResponseEntity<String>(tmpDate.toString(), HttpStatus.OK);
}

Vemos que se corresponde con:

Si queremos documentar la descripción de nuestro controller, añadimos lo que pone en negrita que es la creación de un tag con su nombre y descripción. En el nombre es el tag que debemos poner en nuestro Controller y la descripción, la que saldrá en Swagger.

return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.basePackage("com.swagger.tutorial.demo")).paths(PathSelectors.any()).build()
.tags(new Tag("demo", "Demo Controller description"));
}

En el Controller:

@RestController
@Produces({ "application/json", "application/xml" })
@Api(tags = "demo")
public class DemoController

Con esto veremos la descripción de nuestro controlador. Hay que tener en cuenta que la propiedad description está deprecada a partir de la versión 1.5 de Swagger y ya no deberíamos utilizarla.

Captura de Swagger

--

--