--- title: Create the Micronaut project linkTitle: Create the project description: Set up a Micronaut project with an external REST API integration using declarative HTTP clients. weight: 10 --- ## Set up the project Create a Micronaut project from [Micronaut Launch](https://micronaut.io/launch) by selecting the **http-client**, **micronaut-test-rest-assured**, and **testcontainers** features. Alternatively, clone the [guide repository](https://github.com/testcontainers/tc-guide-testing-rest-api-integrations-in-micronaut-apps-using-wiremock). After generating the project, add the **WireMock** and **Testcontainers WireMock** libraries as test dependencies. The key dependencies in `pom.xml` are: ```xml io.micronaut.platform micronaut-parent 4.1.2 17 4.1.2 netty jitpack.io https://jitpack.io io.micronaut micronaut-http-client compile io.micronaut micronaut-http-server-netty compile io.micronaut.serde micronaut-serde-jackson compile io.micronaut.test micronaut-test-junit5 test io.micronaut.test micronaut-test-rest-assured test org.testcontainers testcontainers-junit-jupiter test org.testcontainers testcontainers test org.wiremock wiremock-standalone 3.2.0 test org.wiremock.integrations.testcontainers wiremock-testcontainers-module 1.0-alpha-13 test ``` This guide builds an application that manages video albums. A third-party REST API handles photo assets. For demonstration purposes, the application uses the publicly available [JSONPlaceholder](https://jsonplaceholder.typicode.com/) API as a photo service. The application exposes a `GET /api/albums/{albumId}` endpoint that calls the photo service to fetch photos for a given album. [WireMock](https://wiremock.org/) is a tool for building mock APIs. Testcontainers provides a [WireMock module](https://testcontainers.com/modules/wiremock/) that runs WireMock as a Docker container. ## Create the Album and Photo models Create `Album.java` using Java records. Annotate both records with `@Serdeable` to allow serialization and deserialization: ```java package com.testcontainers.demo; import io.micronaut.serde.annotation.Serdeable; import java.util.List; @Serdeable public record Album(Long albumId, List photos) {} @Serdeable record Photo(Long id, String title, String url, String thumbnailUrl) {} ``` ## Create the PhotoServiceClient Micronaut provides [declarative HTTP client](https://docs.micronaut.io/latest/guide/#httpClient) support. Create an interface with a method that fetches photos for a given album ID: ```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 getPhotos(@PathVariable Long albumId); } ``` The `@Client(id = "photosapi")` annotation ties this client to a named configuration. Add the following property to `src/main/resources/application.properties` to set the base URL: ```properties micronaut.http.services.photosapi.url=https://jsonplaceholder.typicode.com ``` ## Create the REST API endpoint Create `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)); } } ``` Here's what this controller does: - `@Controller("/api")` maps the controller to the `/api` path. - Constructor injection provides a `PhotoServiceClient` bean. - `@ExecuteOn(BLOCKING)` offloads blocking I/O to a separate thread pool so it doesn't block the event loop. - `@Get("/albums/{albumId}")` maps the `getAlbumById()` method to an HTTP GET request. This endpoint calls the photo service for a given album ID and returns a response like: ```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" } ] } ```