# Crear el proyecto Micronaut


## Configurar el proyecto

Crea un proyecto Micronaut desde [Micronaut Launch](https://micronaut.io/launch)
seleccionando las características **http-client**, **micronaut-test-rest-assured** y
**testcontainers**.

Alternativamente, puedes clonar el
[repositorio de la guía](https://github.com/testcontainers/tc-guide-testing-rest-api-integrations-in-micronaut-apps-using-wiremock).

Después de generar el proyecto, agrega las bibliotecas **WireMock** y **Testcontainers
WireMock** como dependencias de prueba. Las dependencias clave en `pom.xml`
son:

```xml
<parent>
    <groupId>io.micronaut.platform</groupId>
    <artifactId>micronaut-parent</artifactId>
    <version>4.1.2</version>
</parent>

<properties>
    <jdk.version>17</jdk.version>
    <micronaut.version>4.1.2</micronaut.version>
    <micronaut.runtime>netty</micronaut.runtime>
</properties>

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>io.micronaut</groupId>
        <artifactId>micronaut-http-client</artifactId>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>io.micronaut</groupId>
        <artifactId>micronaut-http-server-netty</artifactId>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>io.micronaut.serde</groupId>
        <artifactId>micronaut-serde-jackson</artifactId>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>io.micronaut.test</groupId>
        <artifactId>micronaut-test-junit5</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.micronaut.test</groupId>
        <artifactId>micronaut-test-rest-assured</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.testcontainers</groupId>
        <artifactId>testcontainers-junit-jupiter</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.testcontainers</groupId>
        <artifactId>testcontainers</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.wiremock</groupId>
        <artifactId>wiremock-standalone</artifactId>
        <version>3.2.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.wiremock.integrations.testcontainers</groupId>
        <artifactId>wiremock-testcontainers-module</artifactId>
        <version>1.0-alpha-13</version>
        <scope>test</scope>
    </dependency>
</dependencies>
```

Esta guía construye una aplicación que gestiona álbumes de video. Una API REST de
terceros maneja los recursos de fotos. Con fines de demostración, la aplicación
utiliza la API pública [JSONPlaceholder](https://jsonplaceholder.typicode.com/)
como servicio de fotos.

La aplicación expone un endpoint `GET /api/albums/{albumId}` que llama al servicio
de fotos para obtener las fotos de un álbum específico.
[WireMock](https://wiremock.org/) es una herramienta para construir APIs
simuladas (mock APIs).
Testcontainers proporciona un
[módulo de WireMock](https://testcontainers.com/modules/wiremock/) que ejecuta
WireMock como un contenedor Docker.

## Crear los modelos Album y Photo

Crea `Album.java` utilizando Java records. Anota ambos records con `@Serdeable`
para permitir la serialización y deserialización:

```java
package com.testcontainers.demo;

import io.micronaut.serde.annotation.Serdeable;
import java.util.List;

@Serdeable
public record Album(Long albumId, List<Photo> photos) {}

@Serdeable
record Photo(Long id, String title, String url, String thumbnailUrl) {}
```

## Crear el PhotoServiceClient

Micronaut proporciona soporte para
[clientes HTTP declarativos](https://docs.micronaut.io/latest/guide/#httpClient).
Crea una interfaz con un método que obtenga las fotos para un ID de álbum determinado:

```java
package com.testcontainers.demo;

import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.PathVariable;
import io.micronaut.http.client.annotation.Client;
import java.util.List;

@Client(id = "photosapi")
interface PhotoServiceClient {

    @Get("/albums/{albumId}/photos")
    List<Photo> getPhotos(@PathVariable Long albumId);
}
```

La anotación `@Client(id = "photosapi")` vincula este cliente a una configuración
con nombre. Agrega la siguiente propiedad a
`src/main/resources/application.properties` para establecer la URL base:

```properties
micronaut.http.services.photosapi.url=https://jsonplaceholder.typicode.com
```

## Crear el endpoint de la API REST

Crea `AlbumController.java`:

```java
package com.testcontainers.demo;

import static io.micronaut.scheduling.TaskExecutors.BLOCKING;

import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.PathVariable;
import io.micronaut.scheduling.annotation.ExecuteOn;

@Controller("/api")
class AlbumController {

    private final PhotoServiceClient photoServiceClient;

    AlbumController(PhotoServiceClient photoServiceClient) {
        this.photoServiceClient = photoServiceClient;
    }

    @ExecuteOn(BLOCKING)
    @Get("/albums/{albumId}")
    public Album getAlbumById(@PathVariable Long albumId) {
        return new Album(albumId, photoServiceClient.getPhotos(albumId));
    }
}
```

Esto es lo que hace este controlador:

- `@Controller("/api")` mapea el controlador a la ruta `/api`.
- La inyección por constructor proporciona un bean `PhotoServiceClient`.
- `@ExecuteOn(BLOCKING)` descarga las operaciones de E/S bloqueantes en un
  grupo de hilos separado para que no bloqueen el bucle de eventos.
- `@Get("/albums/{albumId}")` mapea el método `getAlbumById()` a una solicitud
  HTTP GET.

Este endpoint llama al servicio de fotos para un ID de álbum específico y
devuelve una respuesta como:

```json
{
  "albumId": 1,
  "photos": [
    {
      "id": 51,
      "title": "non sunt voluptatem placeat consequuntur rem incidunt",
      "url": "https://via.placeholder.com/600/8e973b",
      "thumbnailUrl": "https://via.placeholder.com/150/8e973b"
    },
    {
      "id": 52,
      "title": "eveniet pariatur quia nobis reiciendis laboriosam ea",
      "url": "https://via.placeholder.com/600/121fa4",
      "thumbnailUrl": "https://via.placeholder.com/150/121fa4"
    }
  ]
}
```

