O Swagger é um dos frameworks mais usados para se documentar API’s REST. Ele facilita para que os clientes que consomem nossas API’s saibam quais os parâmetros nossas operações recebem, qual o retorno, o modelo, o media type retornado JSON, XML, CSV, binário etc. Sendo assim os clientes não precisam necessariamente discutir com a equipe de desenvolvimento da API sobre como usá-la. Pode-se dizer que a grosso modo o Swagger se comporta como o velho WSDL das aplicações SOAP. Sendo assim esse framework valoriza e muito nossas aplicações.
Tomando como base o projeto do post anterior vamos adicionar as configurações necessárias para habilitar o Swagger na aplicação. Para isso abra o arquivo pom.xml e adicione as tags destacadas com comentários no código abaixo.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelversion>4.0.0</modelversion>
<groupid>br.com.erudio</groupid>
<artifactid>simple-rest-example-swagger</artifactid>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-parent</artifactid>
<version>1.3.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
<!-- Adicionando a dependencia do Spring Boot Starter Actuator -->
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-actuator</artifactid>
</dependency>
<!-- Adicione as dependências do Swagger API necessárias para gerar a documentação da aplicação-->
<dependency>
<groupid>com.mangofactory</groupid>
<artifactid>swagger-springmvc</artifactid>
<version>1.0.0</version>
</dependency>
<dependency>
<groupid>org.ajar</groupid>
<artifactid>swagger-spring-mvc-ui</artifactid>
<version>0.4</version>
</dependency>
<dependency>
<groupid>org.apache.tomcat.embed</groupid>
<artifactid>tomcat-embed-jasper</artifactid>
<scope>provided</scope>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-maven-plugin</artifactid>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
<!-- Adicione o repositório do Swagger ao projeto-->
<repository>
<id>jcenter-release</id>
<name>jcenter</name>
<url>http://oss.jfrog.org/artifactory/oss-release-local/</url>
</repository>
</repositories>
<pluginrepositories>
<pluginrepository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</pluginrepository>
</pluginrepositories>
</project>
Feito isto precisamos alterar a classe Application para que ela acione o Swagger quando inicializar a aplicação.
package br.com.erudio;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.mangofactory.swagger.configuration.SpringSwaggerConfig;
import com.mangofactory.swagger.models.dto.ApiInfo;
import com.mangofactory.swagger.plugin.EnableSwagger;
import com.mangofactory.swagger.plugin.SwaggerSpringMvcPlugin;
@Configuration // Define a classe como classe de configuração
@EnableAutoConfiguration // Habilita a autoconfiguração
@EnableSwagger //Habilita o Swagger
@ComponentScan(basePackages = {"br.com.erudio"}) //Escaneia todos os pacotes com o padrão br.com.erudio
public class Application {
//Injeta uma instancia de SpringSwaggerConfig
@Autowired
private SpringSwaggerConfig swaggerConfig;
public static void main(String[] args) {
//Troque esta linha SpringApplication.run(Application.class, args); pela linha abaixo
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
@Bean
public SwaggerSpringMvcPlugin groupOnePlugin() {
return new SwaggerSpringMvcPlugin(swaggerConfig)
//Adiciona as configurações do Swagger ao SwaggerSpringMvcPlugin
.apiInfo(apiInfo()) //Adiciona as propriedades de configuração
.includePatterns("/person.*?", "/greeting.*?") //Habilita o Swagger para os nossos 2 endpoints
.swaggerGroup("admin");
}
private ApiInfo apiInfo() {
ApiInfo apiInfo = new ApiInfo( //Configurações de contato, licença etc não nescessáriamente precisa ser definida
"Swagger With Spring Boot",
"This is a simple application to demonstrate how to work with Swagger in Spring Boot project!",
"Free to use and mess around",
"erudio@gmail.com",
"Open Licence",
"myemail@gmail.com"
);
return apiInfo;
}
}
Agora que o Swagger já está configurado vamos documentar o endpoint Greeting.
package br.com.erudio.web.controllers;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import br.com.erudio.models.Greeting;
@Api(value = "greeting") //Diz ao Swagger que esse é um endpoint e REST deve ser documentado
@RestController
@RequestMapping("/greeting")
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@ApiOperation(value = "Show Greeting Message" )
//Diz ao Swagger que essa operação REST deve ser documentado
@ResponseStatus(HttpStatus.OK)
@RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
Como se pode ver é extremamente simples documentar a nossa API agora vamos vazer o mesmo com o endpoint Person.
package br.com.erudio.web.controllers;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
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.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import br.com.erudio.models.Person;
import br.com.erudio.services.PersonService;
@Api(value = "person") //Diz ao Swagger que esse é um endpoint e REST deve ser documentado
@RestController
@RequestMapping("/person/")
public class PersonController {
@Autowired
private PersonService personService;
@ApiOperation(value = "Find person by ID" )
//Diz ao Swagger que essa operação REST deve ser documentado
@ResponseStatus(HttpStatus.OK)
@RequestMapping(value = "/{personId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public Person get(@PathVariable(value = "personId") String personId){
return personService.findById(personId);
}
@ApiOperation(value = "Find all persons" )
//Diz ao Swagger que essa operação REST deve ser documentado
@ResponseStatus(HttpStatus.OK)
@RequestMapping(value = "/findAll", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public List<person> findAll(){
return personService.findAll();
}
@ApiOperation(value = "Create a new person" )
//Diz ao Swagger que essa operação REST deve ser documentado
@ResponseStatus(HttpStatus.OK)
@RequestMapping(method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Person create(@RequestBody Person person){
return personService.create(person);
}
@ApiOperation(value = "Update an existing person")
//Diz ao Swagger que essa operação REST deve ser documentado
@ResponseStatus(HttpStatus.OK)
@RequestMapping(method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_VALUE)
public Person update(@RequestBody Person person){
return personService.update(person);
}
@ApiOperation(value = "Delete person by ID" )
//Diz ao Swagger que essa operação REST deve ser documentado
@ResponseStatus(HttpStatus.OK)
@RequestMapping(value = "/{personId}", method = RequestMethod.DELETE)
public void delete(@PathVariable(value = "personId") String personId){
personService.delete(personId);
}
}
Não parece mas já terminamos toda a codificação necessária por adicionar o Swagger à nossa API mais uma vez acesse a classe Application e inicie a aplicação como no post anterior. Após inicializada a aplicação acesse a URL:
localhost:8080/sdoc.jsp
Essa é a URL padrão da documentação e nunca tentei alterá-la. Ao acessá-la você verá algo similar a imagem abaixo documentando cada uma das operações dos nossos endpoints. Bastando clicar sobre cada uma para expandir e ver todos os detalhes da mesma.
Na imagem abaixo podemos ver a documentação da operação findAll. Temos a definição do modelo que ela nos retorna, o tipo de dados que ela retorna no caso JSON, os StatusCode que ela pode retornar, se clicarmos em Try Out o Swagger nos permite testar nossas operações. Ao executarmos esse teste a nossa API nos retornou um array de pessoas, o cabeçalho e o StatusCode 200 OK.
Chegamos com este post ao final da série de posts, práticos, sobre serviços REST. Você pode baixar o código deste post aqui e descompactar o arquivo zip e importar na sua IDE preferida ou clonar usando Git:
git clone https://github.com/leandrocgsi/simple-rest-example-swagger.git
Agora você já consegue dar os primeiros passos na criação de serviços REST, conhece conceitos, teóricos e práticos, básicos para executar esse tipo de tarefa. Sendo assim continue ligado no blog, por que no próximos posts iremos detonar o Rock’n Roll com outras tecnologias. É isso aí bons estudos.
Treinamentos relacionados com este post









Muito bom o tutorial, parabéns!!!
Uma dúvida, os requestes mapping do create e do update estão trocados? para criar seria o RequestMethod.Post e para atualizar o RequestMethod.PUT.
Sim Luciana eu acabei invertendo a informação. Coloquei a mensagem de criação no PUT e a de update no POST.
Parabens pelo trabalho!
Obrigado por acompanhar.