Code First
Una vez validado que contamos con el entorno de trabajo adecuado, y que la aplicación arranca correctamente, pasaremos a crear nuestra primera versión de Petstore Lite usando CodeFirst
![]() |
El código de este capítulo se encuentra en la carpeta 02-petstore-codefirst del repositorio de github |
Partiendo del proyecto creado anteriormente, y como queremos proporcionar al equipo de FrontEnd una API REST válida cuanto antes, vamos a trabajar lo primero en la capa http definiendo los Controllers y los DTOs de entrada y salida.
![]() |
Como el Controller creado automáticamente por Micronaut no nos interesa podemos/debemos eliminarlo. |
DTOs
Creamos un DTO en el package dtos para representar el Pet que queremos crear.
1 package com.incsteps.dtos;
2
3 import io.micronaut.serde.annotation.Serdeable;
4 import jakarta.validation.constraints.NotNull;
5
6 @Serdeable
7 public record CreatePetRequest(
8 @NotNull String name,
9 int age
10 ) {
11 }
La anotación @Serdeable nos permite serializar y deserializar el DTO utilizando el formato JSON facilitando su
uso en las llamadas HTTP.
Así mismo, crearemos un DTO para representar el Pet creado.
1 package com.incsteps.dtos;
2
3 import io.micronaut.serde.annotation.Serdeable;
4
5 @Serdeable
6 public record Pet(
7 Long id,
8 String name,
9 int age
10 ) {
11 }
Como podemos ver, el DTO de salida es muy similar al DTO de entrada, incluyendo el ID del Pet creado.
Con estos DTOs ya podemos crear el Controller para crear un nuevo Pet.
1 package com.incsteps.http;
2
3 import com.incsteps.dtos.CreatePetRequest;
4 import com.incsteps.dtos.Pet;
5 // resto de imports eliminados por brevedad
6
7 @Controller("/pets")
8 @Tag(name = "Pets", description = "Operaciones sobre el catálogo de mascotas")
9 public class PetstoreController {
10
11 }
Get Pet by ID
Por ahora vamos a definir solo el interface http para obtener un Pet por su ID pero devolviendo siempre un 404.
1 @Get("/{id}")
2 @Produces(MediaType.APPLICATION_JSON)
3 @Operation(
4 summary = "Obtener mascota por ID",
5 description = "Devuelve los detalles de una mascota concreta dada su clave primaria."
6 )
7 @ApiResponse(
8 responseCode = "200",
9 description = "Mascota encontrada",
10 content = @Content(schema = @Schema(implementation = Pet.class))
11 )
12 @ApiResponse(
13 responseCode = "400",
14 description = "ID suministrado no válido",
15 content = @Content
16 )
17 @ApiResponse(
18 responseCode = "404",
19 description = "Mascota no encontrada",
20 content = @Content
21 )
22 public HttpResponse<Pet> get(
23 @Parameter(description = "Identificador único de la mascota", required = true)
24 @PathVariable("id")
25 @NotNull
26 @Positive Long id
27 ) {
28 return HttpResponse.notFound();
29 }
Post Pet
1 @Post
2 @Produces(MediaType.APPLICATION_JSON)
3 @Operation(
4 summary = "Registrar una nueva mascota",
5 description = "Crea una nueva mascota en el catálogo con los datos proporcionados."
6 )
7 @ApiResponse(
8 responseCode = "201",
9 description = "Mascota creada con éxito",
10 content = @Content(schema = @Schema(implementation = Pet.class))
11 )
12 @ApiResponse(
13 responseCode = "400",
14 description = "Petición no válida (datos faltantes o erróneos)",
15 content = @Content
16 )
17 public HttpResponse<Pet> create(
18 @Parameter(description = "Datos de la mascota a crear", required = true)
19 @Body @NotNull @Valid CreatePetRequest request
20 ) {
21 return HttpResponse.badRequest();
22 }
Al igual que en el caso de obtener un Pet por su ID, por ahora vamos a devolver un bad request.
Delete Pet
De la misma forma que en el caso de obtener un Pet por su ID o crear un nuevo Pet, definiremos un método DELETE para eliminar un Pet.
![]() |
Puedes ver el método completo en el archivo PetstoreController.java en la carpeta 02-petstore-codefirst del repositorio de github. |
Desplegando
Una vez que tenemos definido los endpoints (sin lógica de negocio implementada) procederíamos a desplegarlo. Por ahora nos bastará con ejecutarlo en local y comprobar que Micronaut genere correctamente el contrato OpenAPI a partir de los DTOs y los endpoints definidos.
$ ./gradlew run
En un navegador abrimos la URL http://localhost:8080/swagger/petstore-0.0.yml y veremos el contrato OpenAPI generado.
1 openapi: 3.0.1
2 info:
3 title: petstore
4 version: "0.0"
5 tags:
6 - name: Pets
7 description: Operaciones sobre el catálogo de mascotas
8 paths:
9 /pets:
10 post:
11 tags:
12 - Pets
13 summary: Registrar una nueva mascota
14 description: Crea una nueva mascota en el catálogo con los datos proporcionados.
15 operationId: create
16 requestBody:
17 content:
18 application/json:
19 schema:
20 $ref: "#/components/schemas/CreatePetRequest"
21 (continua)
Iterando Code First
Como puedes ver, Micronaut ha generado a partir del código un recurso OpenAPI en formato YAML que representa el contrato de la API.
Esto nos permite documentar la API y generar clientes de cliente para consumirla. Es decir, una vez desplegada la aplicación podremos crear un MockServer para simular la API en nuestro entorno de desarrollo mientras desarrollamos la funcionalidad de negocio por separado.
UseCases
En el repositorio de ejemplo encontrarás una de las tantas posibles implementaciones. Unas implementarían arquitectura hexagonal, otras una arquitectura simple Controller-Service-Repository.
Cúal elegir (y cómo testearlas) queda fuera del alcance de este libro. Por no complicar los ejemplos y tener un proyecto completo, he optado por crear unos casos de uso como SingletonS, que puedes encontrar en la carpeta 02-petstore-codefirst/src/main/java/com/incsteps/usecases los cuales usa el Controller.

