Java / Gradle

Micronaut HTTP Client

Learn how to use Micronaut low-level HTTP Client. Simplify your code with the declarative HTTP client.

Sergio del Amo, Iván López
On this guide
In this section

Getting Started

In this guide, we will create a Micronaut application written in Java to consume the GitHub API with the Micronaut HTTP Client.

What you will need

To complete this guide, you will need the following:

Solution

We recommend that you follow the instructions in the next sections and create the application step by step. However, you can go right to the completed example.

Writing the Application

Create an application using the Micronaut Command Line Interface or with Micronaut Launch.

mn create-app example.micronaut.micronautguide \
    --features=http-client,graalvm \
    --build=gradle \
    --lang=java \
    --test=junit
Note
If you don’t specify the --build argument, Gradle with the Kotlin DSL is used as the build tool.
If you don’t specify the --lang argument, Java is used as the language.
If you don’t specify the --test argument, JUnit is used for Java and Kotlin, and Spock is used for Groovy.

The previous command creates a Micronaut application with the default package example.micronaut in a directory named micronautguide.

If you use Micronaut Launch, select Micronaut Application as application type and add http-client, and graalvm features.

Note
If you have an existing Micronaut application and want to add the functionality described here, you can view the dependency and configuration changes from the specified features, and apply those changes to your application.

Dependency

To use the Micronaut HTTP Client based on Netty, add the following dependency:

build.gradle
implementation("io.micronaut:micronaut-http-client")

To use the Micronaut HTTP Client based on Java HTTP Client, add the following dependency:

build.gradle
implementation("io.micronaut:micronaut-http-client-jdk")

GitHub API

In this guide, you will consume the GitHub API from a Micronaut application.

In this guide, you will fetch Micronaut Core releases via the List releases endpoint.

This returns a list of releases, which does not include regular Git tags that have not been associated with a release.

This API resource can be consumed by both authenticated and anonymous clients. Initially, you will consume it anonymously, later we will discuss authentication.

Create a record to parse the JSON response into an object:

java/src/main/java/example/micronaut/GithubRelease.java
package example.micronaut;

import io.micronaut.serde.annotation.Serdeable;

@Serdeable
public record GithubRelease(String name, String url) {
}

Configuration

Modify src/main/resources/application.properties to create some configuration parameters.

src/main/resources/application.properties
github.organization=micronaut-projects
github.repo=micronaut-core

To encapsulate type-safe configuration retrieval, we use a @ConfigurationProperties object:

java/src/main/java/example/micronaut/GithubConfiguration.java
package example.micronaut;

import io.micronaut.context.annotation.ConfigurationProperties;
import io.micronaut.context.annotation.Requires;
import io.micronaut.core.annotation.Nullable;

@ConfigurationProperties(GithubConfiguration.PREFIX)
@Requires(property = GithubConfiguration.PREFIX)
public record GithubConfiguration(String organization,
                                  String repo,
                                  @Nullable String username,
                                  @Nullable String token) {
    public static final String PREFIX = "github";
}

JSON Codec Configuration

Add configuration to treat application/vnd.github.v3+json as JSON.

src/main/resources/application.properties
micronaut.codec.json.additional-types[0]=application/vnd.github.v3+json

HTTP Client Service Configuration

Add configuration to associate a service identifier to the GitHub API URL.

src/main/resources/application.properties
micronaut.http.services.github.url=https://api.github.com

Low Level Client

Initially, you will create a Bean which uses the low-level Client API.

Create GithubLowLevelClient:

java/src/main/java/example/micronaut/GithubLowLevelClient.java

Declarative Client

It is time to take a look at support for declarative clients via the Client annotation.

Create GithubApiClient which clearly illustrates how a declarative Micronaut HTTP Client, which is generated at compile-time, simplifies our code.

java/src/main/java/example/micronaut/GithubApiClient.java

Controller

Create a Controller. It uses both (low-level and declarative clients). The Micronaut framework supports Reactive Streams implementations such as RxJava or Project Reactor. Thus, you can efficiently compose multiple HTTP client calls without blocking (which will limit the throughput and scalability of your application).

java/src/main/java/example/micronaut/GithubController.java

Tests

We will mock the GitHub API with some releases

Note
Here we only show a single release. You can add more entries to the file if you want to test with multiple releases.
src/test/resources/single-release.json
[{"url":"https://api.github.com/repos/micronaut-projects/micronaut-core/releases/91622014","assets_url":"https://api.github.com/repos/micronaut-projects/micronaut-core/releases/91622014/assets","upload_url":"https://uploads.github.com/repos/micronaut-projects/micronaut-core/releases/91622014/assets{?name,label}","html_url":"https://github.com/micronaut-projects/micronaut-core/releases/tag/v3.8.4","id":91622014,"author":{"login":"sdelamo","id":864788,"node_id":"MDQ6VXNlcjg2NDc4OA==","avatar_url":"https://avatars.githubusercontent.com/u/864788?v=4","gravatar_id":"","url":"https://api.github.com/users/sdelamo","html_url":"https://github.com/sdelamo","followers_url":"https://api.github.com/users/sdelamo/followers","following_url":"https://api.github.com/users/sdelamo/following{/other_user}","gists_url":"https://api.github.com/users/sdelamo/gists{/gist_id}","starred_url":"https://api.github.com/users/sdelamo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sdelamo/subscriptions","organizations_url":"https://api.github.com/users/sdelamo/orgs","repos_url":"https://api.github.com/users/sdelamo/repos","events_url":"https://api.github.com/users/sdelamo/events{/privacy}","received_events_url":"https://api.github.com/users/sdelamo/received_events","type":"User","site_admin":false},"node_id":"RE_kwDOB2eaPM4Fdgp-","tag_name":"v3.8.4","target_commitish":"3.8.x","name":"Micronaut Framework 3.8.4","draft":false,"prerelease":false,"created_at":"2023-02-07T15:53:03Z","published_at":"2023-02-07T15:53:05Z","assets":[{"url":"https://api.github.com/repos/micronaut-projects/micronaut-core/releases/assets/94667997","id":94667997,"node_id":"RA_kwDOB2eaPM4FpITd","name":"artifacts.zip","label":"","uploader":{"login":"github-actions[bot]","id":41898282,"node_id":"MDM6Qm90NDE4OTgyODI=","avatar_url":"https://avatars.githubusercontent.com/in/15368?v=4","gravatar_id":"","url":"https://api.github.com/users/github-actions%5Bbot%5D","html_url":"https://github.com/apps/github-actions","followers_url":"https://api.github.com/users/github-actions%5Bbot%5D/followers","following_url":"https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}","gists_url":"https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}","starred_url":"https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/github-actions%5Bbot%5D/subscriptions","organizations_url":"https://api.github.com/users/github-actions%5Bbot%5D/orgs","repos_url":"https://api.github.com/users/github-actions%5Bbot%5D/repos","events_url":"https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}","received_events_url":"https://api.github.com/users/github-actions%5Bbot%5D/received_events","type":"Bot","site_admin":false},"content_type":"application/zip","state":"uploaded","size":28063979,"download_count":33,"created_at":"2023-02-07T16:18:05Z","updated_at":"2023-02-07T16:18:06Z","browser_download_url":"https://github.com/micronaut-projects/micronaut-core/releases/download/v3.8.4/artifacts.zip"},{"url":"https://api.github.com/repos/micronaut-projects/micronaut-core/releases/assets/94669478","id":94669478,"node_id":"RA_kwDOB2eaPM4FpIqm","name":"multiple.intoto.jsonl","label":"","uploader":{"login":"github-actions[bot]","id":41898282,"node_id":"MDM6Qm90NDE4OTgyODI=","avatar_url":"https://avatars.githubusercontent.com/in/15368?v=4","gravatar_id":"","url":"https://api.github.com/users/github-actions%5Bbot%5D","html_url":"https://github.com/apps/github-actions","followers_url":"https://api.github.com/users/github-actions%5Bbot%5D/followers","following_url":"https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}","gists_url":"https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}","starred_url":"https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/github-actions%5Bbot%5D/subscriptions","organizations_url":"https://api.github.com/users/github-actions%5Bbot%5D/orgs","repos_url":"https://api.github.com/users/github-actions%5Bbot%5D/repos","events_url":"https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}","received_events_url":"https://api.github.com/users/github-actions%5Bbot%5D/received_events","type":"Bot","site_admin":false},"content_type":"application/octet-stream","state":"uploaded","size":65612,"download_count":34,"created_at":"2023-02-07T16:32:49Z","updated_at":"2023-02-07T16:32:49Z","browser_download_url":"https://github.com/micronaut-projects/micronaut-core/releases/download/v3.8.4/multiple.intoto.jsonl"}],"tarball_url":"https://api.github.com/repos/micronaut-projects/micronaut-core/tarball/v3.8.4","zipball_url":"https://api.github.com/repos/micronaut-projects/micronaut-core/zipball/v3.8.4","body":"<!-- Release notes generated using configuration in .github/release.yml at 3.8.x -->\r\n\r\n\r\n## What's Changed\r\n\r\n### Bugs 🐛\r\n* Allow programmatic logback config if xml config is absent (#8674)\r\n* Tweak uri to account for WebLogic/Windows URIs by @mattmoss in https://github.com/micronaut-projects/micronaut-core/pull/8704\r\n\r\n### Docs 📖\r\n* Docs on self-signed cert setup (#8684)\r\n\r\n### Dependency Upgrades 🚀\r\n\r\n* Micronaut Test to 3.8.2 (#8728)\r\n* Micronaut OpenAPI to 4.8.3 (#8724)\r\n* Micronaut Data to 3.9.6 (#8711)\r\n* Micronaut Rabbit to 3.4.1 (#8709)\r\n* Micronaut Azure to 3.7.1 (#8682)\r\n* Micronaut Micrometer to 4.7.2 (#8681)\r\n\r\n### Tests ✅\r\n\r\n* Require docker for test (#8698)\r\n* Add octet stream serialization to the TCK (#8712)\r\n\r\n**Full Changelog**: https://github.com/micronaut-projects/micronaut-core/compare/v3.8.3...v3.8.4","mentions_count":1}]

Create a test to verify that both clients work as expected, and the controller echoes the output of the GitHub API in a Reactive way.

java/src/test/java/example/micronaut/GithubControllerTest.java

Testing the Application

To run the tests:

./gradlew test

Then open build/reports/tests/test/index.html in a browser to see the results.

HTTP Client Filter

Often, you need to include the same HTTP headers or URL parameters in a set of requests against a third-party API or when calling another Microservice. To simplify this, the Micronaut framework includes the ability to define HttpClientFilter classes that are applied to all matching HTTP clients.

For a real world example, let us provide GitHub Authentication via an HttpClientFilter. Follow the steps in to create your own Personal Token. Then you can use those credentials to access the GitHub API using Basic Auth.

Create a Filter:

java/src/main/java/example/micronaut/GithubFilter.java

Configuration Parameters

Add your GitHub username and token to src/main/resources/application.properties

github.organization=micronaut-projects
github.repo=micronaut-core
github.username=yourgithubusername
github.token=xxxxxxxxxxxx

Add a logger to src/main/resources/logback.xml to see the HTTP client output.

<logger name="io.micronaut.http.client" level="TRACE"/>

If you run again the tests, you will see the that the Filter is invoked and HTTP Basic Auth is used against GitHub API.

13:09:56.662 [default-nioEventLoopGroup-1-4] DEBUG i.m.h.client.netty.DefaultHttpClient - Sending HTTP GET to https://api.github.com/repos/micronaut-projects/micronaut-core/releases
13:09:56.663 [default-nioEventLoopGroup-1-4] TRACE i.m.h.client.netty.DefaultHttpClient - User-Agent: Micronaut HTTP Client
13:09:56.663 [default-nioEventLoopGroup-1-4] TRACE i.m.h.client.netty.DefaultHttpClient - Accept: application/json
13:09:56.663 [default-nioEventLoopGroup-1-4] TRACE i.m.h.client.netty.DefaultHttpClient - Authorization: MASKED
13:09:56.664 [default-nioEventLoopGroup-1-4] TRACE i.m.h.client.netty.DefaultHttpClient - host: api.github.com

Generate a Micronaut Application Native Executable with GraalVM

We will use GraalVM, an advanced JDK with ahead-of-time Native Image compilation, to generate a native executable of this Micronaut application.

Compiling Micronaut applications ahead of time with GraalVM significantly improves startup time and reduces the memory footprint of JVM-based applications.

Note
Only Java and Kotlin projects support using GraalVM’s native-image tool. Groovy relies heavily on reflection, which is only partially supported by GraalVM.

GraalVM Installation

The easiest way to install GraalVM on Linux or Mac is to use SDKMan.io.

Java 25
sdk install java 25.0.2-graal

For installation on Windows, or for a manual installation on Linux or Mac, see the GraalVM Getting Started documentation.

The previous command installs Oracle GraalVM, which is free to use in production and free to redistribute, at no cost, under the GraalVM Free Terms and Conditions.

Alternatively, you can use the GraalVM Community Edition:

Java 25
sdk install java 25.0.2-graalce

Native Executable Generation

To generate a native executable using Gradle, run:

./gradlew nativeCompile

The native executable is created in build/native/nativeCompile directory and can be run with build/native/nativeCompile/micronautguide.

It is possible to customize the name of the native executable or pass additional parameters to GraalVM:

build.gradle

Next Steps

Help with the Micronaut Framework

The Micronaut Foundation sponsored the creation of this Guide. A variety of consulting and support services are available.

License

Note
All guides are released with an Apache License 2.0 for the code and a Creative Commons Attribution 4.0 license for the writing and media (images).