04 - API First: el contrato antes del código
En el hito de partida la aplicación se construyó primero en código y el contrato quedó implícito: nadie ajeno al código podía conocer GET /api/products sin leer su implementación. Este hito aplica el tema 02 — API First: toda la API del módulo de catálogo — ahora con catálogos y con la paginación que el listado plano ya necesita — se diseña y se revisa antes de implementarla, y el contrato — un documento OpenAPI — pasa a ser la fuente de verdad.
| Pieza | Cambio en este hito |
|---|---|
| Contrato | Nace openapi.yaml (v0.1.0): catálogos, productos, listado paginado y reglas 409 |
controller | El listado plano de la partida desaparece; las operaciones nuevas se implementan desde el contrato |
| Herramientas | El esqueleto se genera con openapi-generator; Swagger UI (springdoc) lo hace navegable y ejecutable |
1. Diseñar el documento
- Redactar
openapi.yamlcon la API completa del módulo de catálogo:
| Operación | Petición | Respuestas |
|---|---|---|
| Listado de catálogos | GET /api/catalogs | 200 · Catalog[] |
| Ficha de catálogo | GET /api/catalogs/{id} | 200 · 404 |
| Alta de catálogo | POST /api/catalogs | 201 |
| Modificación de catálogo | PUT /api/catalogs/{id} | 200 · 404 |
| Borrado de catálogo | DELETE /api/catalogs/{id} | 204 · 404 · 409 |
| Productos de un catálogo | GET /api/catalogs/{id}/products?page&size | 200 · 404 |
| Ficha de producto | GET /api/products/{id} | 200 · 404 |
| Alta de producto | POST /api/products | 201 · 404 |
| Modificación de producto | PUT /api/products/{id} | 200 · 404 |
| Borrado de producto | DELETE /api/products/{id} | 204 · 404 |
- Esquemas:
CatalogyCatalogRequest;Product(respuesta, conidycatalogId) yProductRequest(concatalogId, sinid);ProductPagepara el listado paginado del catálogo —contentmás los metadatospage,size,totalElementsytotalPages; yProblem(RFC 9457:type,title,status,detail) para los errores. Los 404 de catálogo o producto inexistente y los 409 de estado — nombre de catálogo repetido, catálogo con productos — se declaran también en el contrato. - La paginación se define en el contrato:
page(desde 0, por defecto 0) ysize(por defecto 10) como parámetros deGET /api/catalogs/{id}/products; la respuesta lleva siempre los metadatos. - Aún sin constraints de validación: llegan en el hito 05; la especificación de este hito describe las operaciones y sus errores de estado, no el formato de los datos.
- Esta primera versión se redacta y se revisa antes de generar código: es el momento de acordar el contrato.
- El documento se guarda en
src/main/resources/openapi.yaml, se versiona en el repositorio y suinfo.versionsube en cada hito que toque la API.
El listado plano de la partida desaparece: veintiocho productos en una sola respuesta no escala y no deja navegar por catálogos. El contrato lo sustituye por el subrecurso paginado
GET /api/catalogs/{id}/products. Es la primera decisión que el contrato toma sobre el código.
2. Generar desde el contrato
- El generador openapi-generator — integrado como plugin de Maven del modo que muestra el tema 02 — produce, como código fuente que nunca se edita a mano, las interfaces de la API y los elementos del esquema del contrato.
- Regenerar con
mvn compiletras cada cambio delopenapi.yaml: el esqueleto resultante es la guía de lo que queda por implementar.
3. Implementar desde el contrato
- Cada operación nueva baja por las capas de la partida: métodos nuevos en los servicios y
SQLde inserción, modificación o borrado en la persistencia JDBC; el mecanismo sigue siendo el de 1.º DAW. - El listado de productos de un catálogo sale paginado: el corte y los metadatos (
page,size,totalElements,totalPages) se resuelven con JDBC a mano — sin Spring Data, que llega con el hito 07. El contrato exige la respuesta completa con sus metadatos en cada listado. - Los estados declarados en el contrato se cumplen: 404 para catálogo o producto inexistente y para el producto cuyo
catalogIdapunta a un catálogo que no existe; 409 si el nombre del catálogo se repite al crear o modificar, y si se intenta borrar un catálogo con productos (la comprobación, antes del borrado).
4. Swagger UI
- springdoc monta la doble vista del contrato: el documento generado desde el código en
/v3/api-docsy la UI ejecutable en/swagger-ui.html, para revisar y probar cada operación.
Comprobación
- Swagger UI muestra catálogos y productos y permite ejecutar cada operación, incluida la paginación.
- Las operaciones responden según el contrato (200 / 201 / 204 / 404 / 409 donde toque).
- El listado paginado devuelve los metadatos correctos: el catálogo
Periféricos(12 productos) reparte en 2 páginas consize10. - Borrar un catálogo con productos responde 409; repetir su nombre también.
- El esqueleto del contrato — interfaces y esquemas — está generado y no se ha editado a mano.
- El
openapi.yamlestá en el repositorio coninfo.version0.1.0. - Commit y tag
hito-04.
A partir de ahora el contrato manda: todo cambio de la API se escribe primero en
openapi.yaml y se regenera. Los hitos que no tocan la API no lo tocan.
Siguiente hito: hito 05 — Validación e invariancias.