Pollito Blog
January 2, 2024

Desarrollo basado en contratos 4: Generando interfaces para controladores

Posted on January 2, 2024  •  4 minutes  • 737 words  • Other languages:  English

Uso del plugin swagger codegen maven para generar código implementable del controlador.

Consulta el repositorio de github

Esta es una continuación de Desarrollo basado en contratos 3: Creación de contratos .

Todo lo que haremos aquí, lo puedes encontrar en el repositorio de github.

Spring City Explorer - Backend: Branch feature/cdd-4

Pequeño fix a los archivos OpenAPI.yaml antes de continuar

En los archivos OAS, cuando mencionamos los elementos de una enumeración, es útil enumerar cada elemento entre comillas.

En nuestro proyecto actual, esto es importante porque tenemos algunas enumeraciones que tienen el elemento NO sin las comillas, y la generación automática de código interpretará NO como FALSE. Esto podría causar algunos problemas en el futuro.

Antes del fix:

enum: [published_desc, published_asc, popularity]

Después del fix:

enum: ["published_desc", "published_asc", "popularity"]

¿Qué buscamos lograr?

La idea es que en el momento de la compilación, de alguna manera mágica pero configurable, aparezca código generado automáticamente en la carpeta de destino de nuestro proyecto, que represente el comportamiento que queremos que tengan nuestros controladores.

diagram

Agregando el plugin swagger codegen maven a nuestra base de código

Para esto, usaré el conocimiento proporcionado por Ammar Siddiqui en su repositorio de github increment-service y su video de youtube Swagger Codegen en 20 minutos!.

No seguiré el vídeo exactamente paso a paso, sino las ideas principales que expone.

Agregando dependencias y complementos a pom.xml

Recuerda que puedes consultar el archivo pom.xml final en el repositorio de github del proyecto.

Aquí hay una breve descripción de las dependencias agregadas:

Finalmente, el complemento que hará el trabajo pesado, io.swagger.codegen.v3 (swagger-codegen-maven-plugin)

maven compile -> ¡Código generado!

Ahora, cada vez que se realice la tarea “maven compile”, encontrarás código generado en target/generated-sources/swagger/controllerinterfaces.

Si exploras estos archivos .java, inmediatamente notarás que son bastante complejos, con muchas anotaciones, comentarios y, obviamente, material generado automáticamente. Y esta es la afirmación principal que quiero dejar en tu cabeza después de leer este blog:

Los complejos procesos descritos en la especificación OpenAPI deben automatizarse, permitiendo a los desarrolladores centrarse en sus responsabilidades de negocio principales.

Pollito, en su propio blog

Creando controladores

Ahora creamos los controladores dentro de un paquete de controladores en nuestra carpeta src/main/java. Para cada controlador:

Debería verse así:

Estructura de carpetas

folder structure

ArticleController

package dev.pollito.springcityexplorer.controller;

import dev.pollito.springcityexplorer.api.ArticleApi;
import dev.pollito.springcityexplorer.models.Articles;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ArticleController implements ArticleApi {
    @Override
    public ResponseEntity<Articles> getArticlesByCountry(String country, Integer limit, Integer offset) {
        return null;
    }
}

CommentController

package dev.pollito.springcityexplorer.controller;

import dev.pollito.springcityexplorer.api.CommentApi;
import dev.pollito.springcityexplorer.models.CommentPostBody;
import dev.pollito.springcityexplorer.models.Comments;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CommentController implements CommentApi {
    @Override
    public ResponseEntity<Comments> getComments(Integer limit, Integer offset) {
        return null;
    }

    @Override
    public ResponseEntity<Void> postComment(CommentPostBody body) {
        return null;
    }
}

WeatherController

package dev.pollito.springcityexplorer.controller;

import dev.pollito.springcityexplorer.api.WeatherApi;
import dev.pollito.springcityexplorer.models.Weather;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class WeatherController implements WeatherApi {
    @Override
    public ResponseEntity<Weather> getWeatherByCity(String city) {
        return null;
    }
}

Si todo salió bien, ahora podrás ver en la sección Spring -> MVC de tu IDE los endpoints generados por la implementación de las interfaces, con todas las anotaciones adecuadas (RequestMapping, RequestParam, NotNull, Valid, etc.). Éste es un trabajo que nos ahorramos de hacer.

endpoints

Ejecutando la aplicación actual

Ejemplo 200 OK

Todas las implementaciones actuales devuelven nulo, por lo que no hay cuerpo en la respuesta, pero obtenemos el estado OK.

200 OK

Ejemplo 400 Bad request

Bad params

Próximos pasos

Hey, check me out!

You can find me here