1. Introducción

Hola a todos y bienvenidos a un nuevo post de nuestro querido blog!. Swagger es un conjunto de reglas o especificaciones que nos ayudan a documentar nuestras APIs. Veremos cómo añadir de forma muy sencilla el módulo swagger de springfox para documentar las apis que expongamos a un proyecto SpringBoot.

Os podéis descargar el código de mi GitHub que se encuentra aquí.

Tecnologías empleadas:

  • Java 8
  • Gradle 4.6
  • SpringBoot 2.1.8.RELEASE
  • SpringFox Swagger 2.9.2

2. Requisitos previos

El proyecto ha sido montado sobre gradle, así que si no lo tienes instalado deberás.

  1. Descargar gradle de la web oficial
  2. Descomprimir los binarios en un directorio dentro de tu filesystem
  3. Importar el directorio /bin del gradle a la variable de entorno PATH

Para verificar que hemos configurado gradle correctamente deberemos hacer

gradle -v

3. Ficheros

Añadimos las dependencias org.springframework.boot:spring-boot-starter-web, io.springfox:springfox-swagger2 y io.springfox:springfox-swagger-ui. La primera es la encargada de crear la configuración básica para levantar un controlador rest en SpringBoot. Las otras dos nos permitirán documentar las apis de nuestro proyecto de forma automática.

group 'com.jorgehernandezramirez.spring.springboot.swagger'
version '1.0-SNAPSHOT'

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.1.8.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

sourceCompatibility = 1.8

springBoot {
    mainClassName = "com.jorgehernandezramirez.spring.springboot.swagger.Application"
}

repositories {
    mavenLocal()
    mavenCentral()
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    compile("io.springfox:springfox-swagger2:${swagger_version}")
    compile("io.springfox:springfox-swagger-ui:${swagger_version}")
}

Además a través de la dependencia io.springfox:springfox-swagger-ui podremos acceder a la definición de nuestra api a través navegador y testearla!

Definimos nuestra clase main.

package com.jorgehernandezramirez.spring.springboot.swagger;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public Application(){
        //For Spring
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Definimos un controlador de pruebas

package com.jorgehernandezramirez.spring.springboot.swagger.controller;

import com.jorgehernandezramirez.spring.springboot.swagger.controller.dto.UserDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping("/user")
public class UserController {

    private static Logger LOGGER = LoggerFactory.getLogger(UserController.class);

    public UserController(){
        //For Spring
    }

    @RequestMapping(method = RequestMethod.POST)
    public void create(@RequestBody UserDto userDto) {
        LOGGER.info("Se va a proceder a crear el usuario {}", userDto);
    }

    @RequestMapping(method = RequestMethod.GET)
    public List<UserDto> getUsers() {
        return Arrays.asList(new UserDto("1", "Jorge"), new UserDto("2", "Jose"));
    }
}
package com.jorgehernandezramirez.spring.springboot.swagger.controller.dto;

import java.util.Objects;

public class UserDto {

    private final String id;

    private final String name;

    public UserDto(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UserDto userDto = (UserDto) o;
        return Objects.equals(id, userDto.id) &&
                Objects.equals(name, userDto.name);
    }

    @Override
    public int hashCode() {

        return Objects.hash(id, name);
    }

    @Override
    public String toString() {
        return "UserDto{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

Por último nos basta con utilizar la anotación @EnableSwagger2 dentro de una clase de configuración y crear un bean de la clase Docket para que se genere de forma automática la definición de la api.

package com.jorgehernandezramirez.spring.springboot.swagger.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
    @Bean
    public Docket buildDocket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.jorgehernandezramirez.spring.springboot.swagger.controller"))
                .paths(PathSelectors.any())
                .build();
    }
}

4. Probando la aplicación

Para compilar la aplicación deberemos ejecutar

gradle buildNeeded

y arrancamos

java -jar SpringBootSwagger-1.0-SNAPSHOT.jar

Accedemos a la url http://localhost:8080/swagger-ui.html y voila!

Hemos de tener presente que realmente la definición de la api se expone a través del endpoint http://localhost:8080/api/v2/api-docs. El endpoint anterior no es más que el resultado de la definición en html para una mejor visualización

5. Referencias