Swagger / Java & Spring Boot
La programación, además de ser funcional, debe ser elegante, limpia y legible. A día de hoy están más de moda que nunca las APIs para crear servicios web o microservicios. Una de las características bien buscadas a lograr en una API es que sea legible y que la podamos probar para poder ver sus entradas y salidas.
Para este escenario cuando desarrollamos en Java el “estándar defacto” se llama Swagger, en el diccionario, cuando buscamos que significa esta palabra refiere a una persona que es admirada por su estilo, forma de ser y por la forma en que habla y actúa. En este artículo entonces hablaremos de como crear un API que sea “swagger”.
¿Qué haremos en este artículo?
Crearemos un proyecto sencillo que permitirá añadir y buscar personas, usaremos como modelo una Lista en Java para almacenar y buscar las personas. El objetivo lo centraremos en el API y en la configuración de Swagger para usarlo.
Usaremos Java con el marco de trabajo Spring Boot, pero swagger lo puedes usar desde otros lenguajes, ya que es, en sí una especificación.
Creando el proyecto
Para crear el proyecto yo en lo personal empleo Intell IJ y la integración que este posee con Spring Intitializr, si lo usas, crea un proyecto Spring Boot con el módulo web seleccionado, también puedes hacerlo directo en la página o siemplemente usando el POM que aparece debajo. Al mismo ya le he añadido las dependencias para swagger.
Una vez con las dependencias listas en el POM, vamos entonces a ver la estructura de nuestro proyecto ejemplo:
Paquetes
- common: En este paquete crearemos la clase SwaggerConfig, la cual es a los objetivos de este artículo la más importante, puesto que nos permitirá configurar a Swagger para nuestro proyecto.
- model: Definiremos un sencillo modelo para trabajar llamado Persona.
- controller: Se implementa un controlador para nuestro ejemplo que añadirá personas a una lista y los buscará por edad.
- web: Es aquí donde está el otro punto de atención, en este paquete crearemos PersonaAPI, donde estarán las funciones (endpoints REST) que swagger documentará.
Componentes de Swagger
- swagger: Componente básico encargado de detectar las APIs creadas por nuestra aplicación, determina los JSON de entrada/salida así como ofrece la lógica para comunicarnos con el API.
- swagger-ui: Es la interfaz que empleando el componente anterior facilita y documenta la interacción con nuestra API.
Código de interés
En nuestra aplicación, hemos creado en el paquete common la clase SwaggerConfig, en su interior la implementación:
@Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build() .apiInfo(this.apiInfo()); } private ApiInfo apiInfo() { return new ApiInfo( "REST API", "REST API de ejemplo para sacavix.com.", "v1.0", "Todos los derechos otorgados", new Contact("Yoandy Pérez Villazón", "https://blog.sacavix.com", "sacavix@gmail.com"), "Licencia del API", "http://www.fsf.org", Collections.emptyList()); } }
El método api(), es el método principal y el que le indica a swagger que todos (any, cualquiera) nuestros endpoint REST los “mapee” y documente construyendo la ayuda para ellos, además le indica que la Información general del api la lea desde el método apiInfo() que hemos implementado.
Con este código que hemos escrito ya es suficiente para documentar nuestra API.
El código que se muestra a continuación es el normal del controlador REST, no tiene nada de especial que tenga que ponerse para que se “autodocumente con Swagger”.
Clase Persona, del paquete /model
public class Persona { private String nombre; private int edad; public Persona() { } public Persona(String nombre, int edad) { this.nombre = nombre; this.edad = edad; } public String getNombre() { return nombre; } public int getEdad() { return edad; } }
Clase PersonaLista del paquete controller
@Component public class PersonaLista { private List<Persona> listaPersonas; public PersonaLista() { listaPersonas = new ArrayList<>(); } public Persona adicionarPersona(Persona persona) throws Exception { int size = listaPersonas.size(); this.listaPersonas.add(persona); if (size + 1 == this.listaPersonas.size()) return persona; else throw new Exception("La persona no fue añadida"); } public List<Persona> buscarPersonasPorEdad(int edad) { return this.listaPersonas.stream() .filter(persona -> edad == persona.getEdad()) .collect(Collectors.toList()); } }
El controlador que posee nuestra API, llamada PersonaAPI del paquete web.
@RestController public class PersonaAPI { @Autowired PersonaLista personaLista; @RequestMapping(value = "/adicionarPersona", method = RequestMethod.POST) public Persona crearPersona(@RequestBody Persona persona) { try { return this.personaLista.adicionarPersona(persona); } catch (Exception e) { return null; } } @RequestMapping(value = "/buscarPersona", method = RequestMethod.GET) public List<Persona> buscarPersonaPorEdad(@RequestParam Integer edad){ return this.personaLista.buscarPersonasPorEdad(edad.intValue()); } }
Con el código anterior, swagger-ui nos crea una vista con la documentación del API, la misma es accesible desde http://localhost:8080/swagger-ui.html, se muestra como aparece debajo.
Si desglosamos buscarPersona por ejemplo:
Como puede verse swagger nos crea un sandbox para probar directamente nuestra API, algo que es un valor agregado muy valioso.
Agregando más documentación al API
Si queremos un API más especificada podemos añadir en nuestro controlador REST anotaciones para esto.
- Para documentar la clase añadimos @Api encima de PersonaAPI
- Para especificar la función del método y lo que devuelve lo podemos hacer con la anotación @ApiOperation
- La especificación de códigos HTTP de respuesta lo hacemos con @ApiResponse
Estas tres anotaciones las podemos ver en la práctica aquí:
@RestController
@Api(value="personasapi", description="Operaciones sobre la clase Persona")
public class PersonaAPI {
@Autowired
PersonaLista personaLista;
@ApiOperation(value = "Añadir una persona", response = Persona.class)
@RequestMapping(value = "/adicionarPersona", method = RequestMethod.POST)
public Persona crearPersona(@RequestBody Persona persona) {
try {
return this.personaLista.adicionarPersona(persona);
} catch (Exception e) {
return null;
}
}
@ApiOperation(value = "Ver una lista de personas por edad", response = Persona[].class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Personas obtenidas correctamente"),
@ApiResponse(code = 401, message = "No estas autorizado para ver obtener personas"),
@ApiResponse(code = 403, message = "Está tratando de acceder a una persona no permitida"),
@ApiResponse(code = 404, message = "La persona de esa edad no fue encontrada")
})
@RequestMapping(value = "/buscarPersona", method = RequestMethod.GET)
public List<Persona> buscarPersonaPorEdad(@RequestParam Integer edad){
return this.personaLista.buscarPersonasPorEdad(edad.intValue());
}
}
La creación de entidades clientes a partir de Swagger: swagger-codegen
Si Swagger de por si ya es bastante completo, existe swagger-codegen, una utilidad escrita en Java que es capaz de leer nuestra API con swagger y generar entidades clientes para mappear nuestra API y acelerar la creación de aplicaciones clientes que consumen nuestra API.
Con swagger-codegen podemos generar código para ActionScript, Ada, Apex, Bash, C# (.net 2.0, 4.0 or later), C++ (cpprest, Qt5, Tizen), Clojure, Dart, Elixir, Eiffel, Erlang, Go, Groovy, Haskell (http-client, Servant), Java (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java), Kotlin, Lua, Node.js (ES5, ES6, AngularJS with Google Closure Compiler annotations) Objective-C, Perl, PHP, PowerShell, Python, R, Ruby, Rust, Scala (akka, http4s, swagger-async-httpclient), Swift (2.x, 3.x, 4.x), Typescript (Angular1.x, Angular2.x, Fetch, jQuery, Node).
El proceso es tan sencillo como descargar el JAR y ejecutar el comando generador con el lenguaje destino al que queremos generar.
wget http://central.maven.org/maven2/io/swagger/swagger-codegen-cli/2.2.3/swagger-codegen-cli-2.2.3.jar -O swagger-codegen-cli.jar
Para generar un cliente para nuestra API sería por ejemplo:
java -jar swagger-codegen-cli.jar generate -i http://localhost:8080/v2/api-docs -l php -o /home/usuario/api-cliente
Conclusiones
¿Crees que swagger es útil?, a partir de ahora no lo dudes más, cada vez que crees un API REST documentala bien, usa swagger, tiene implementaciones para otros lenguajes.
Chào mừng các bạn đến với ĐIỆN LẠNH Bách Khoa Hitech. http://xn--b1aedkcmhpgcbxz7l.xn--p1ai/bitrix/redirect.php?event1=&event2=&event3=&goto=https://suadieuhoagiare247.com/san-pham/sua-dieu-hoa-panasonic/
Hi, i think that i saw you visited my weblog thus i came
to “return the favor”.I am trying to find things to enhance my website!I
suppose its ok to use some of your ideas!!
Hi, thanks for your comment, please no problem, if I can help you with something, just tell me.
Tips nicely considered..
Seriously tons of fantastic knowledge!
It’s amazing in favor of me to have a web site, which is helpful designed for my knowledge.
thanks admin
What’s up friends, how is the whole thing, and what you wish for to say regarding this article,
in my view its truly amazing in favor of me.
This post is in fact a good one it assists new internet viewers, who are wishing in favor of blogging.
This is a great tip especially to those new to the blogosphere.
Simple but very accurate info… Appreciate your sharing this one.
A must read article! https://Www.Faceliftdentistry.com/overbite/
This is very interesting, You’re a very skilled blogger.
I’ve joined your rss feed and look forward to seeking more of your magnificent
post. Also, I’ve shared your website in my social networks! http://Ironthundersaloon.com/
Swagger con Java & Spring Boot, documenta y prueba tus APIs http://ionliga.nethttp://adminsituspoker.com
Thank you so much I need to know this!
Great info, thanks for sharing it!
Really like your blog thanks! Check my blog out to if you like.