How to Integrate Binance API with Quarkus and MicroProfile Rest Client in Java

REST APIs are a common way of exchanging data between different applications or services. However, consuming REST APIs from a Java application can be tedious and error-prone, especially if you have to deal with low-level HTTP details, serialization and deserialization, error handling and more.

Fortunately, Quarkus provides a simple and elegant way of creating and using REST clients with the help of MicroProfile Rest Client. This is a specification that defines a type-safe and declarative approach for invoking RESTful services.

In this article, we will see how to create a REST client in Quarkus using MicroProfile Rest Client, specifically to retrieve data from Binance API. Binance is a popular cryptocurrency exchange platform that offers various APIs for accessing market data, account information, trading operations and more. We will use the Binance API as an example of a real-world REST service that we can consume from our Quarkus application.

Set up the REST Client

@Path("/")
@RegisterRestClient
public interface BinanceRestClient {
    @GET
    @Path("/api/v3/klines")
    List<Candlestick> getCandlestickBars(
            @QueryParam("symbol") String symbol,
            @QueryParam("interval") String interval,
            @QueryParam("limit") Integer limit,
            @QueryParam("startTime") Long startTime,
            @QueryParam("endTime") Long endTime);
}

All you can see is the definition of the API all-in-one interface, see the official documentation - Kline/Candlestick Data.

The only missing part that allows Quarkus to generate the actual implementation is the Base URL, which can be configured in the application.properties file:

quarkus.rest-client."dev.dvalentino.demo.quarkus.binance.client.BinanceRestClient".url=https://api.binance.com

At this point, to test the REST client we can set a Resource endpoint on our demo application so we can call it with any tool, such as postman, curl, http, etc...

Defining a resource API to test the REST client

Let's set an endpoint with the version /api/v1/klines, inject our REST Client and use it straight away, Quarkus will do all the rest providing an implementation:

@Path("/api/v1/klines")
public class KLinesResource {

    private final BinanceRestClient binanceRestClient;

    public KLinesResource(@RestClient BinanceRestClient binanceRestClient) {
        this.binanceRestClient = binanceRestClient;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<Candlestick> getKLines() {

        LocalDateTime currenTime = LocalDateTime.now();

        return binanceRestClient.getCandlestickBars("BTCUSDT", "1m", 5,
                currenTime.minusMinutes(15).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(),
                currenTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
        );
    }
}

Microprofile framework will generate a JAX RS (Jakarta RESTful Web Services) implementation, a Java API for building RESTful web services. We have annotated the Resource class with @Path("/api/v1/klines"), indicating that it represents the endpoint accessible at the URL path "/api/v1/klines", also note that we are injecting the BinanceRestClient using the @RestClient annotation.

We are using the current date and time, so that we can retrieve the most recent 5 one-minute candlestick bars ("K-lines") of historical price data for the trading pair "BTCUSDT" (Bitcoin to USDT) using the binanceRestClient.getCandlestickBars() method. The method takes parameters such as the symbol, the interval (1 minute in this case), the number of candlestick bars to retrieve (5), and a time range defined by the timestamps of 15 minutes ago and the current time.

Nice to know
Quarkus hot reload mechanism compiles the changed code and dynamically updates the running application, which gives us the flexibility to edit directly those parameters for testing purposes.

Build and run (Hot-Reload)

Clone the code sample from GitHub

git clone git@github.com:davide-valentino/demo-quarkus-binance.git

And run the Quarkus app:

./gradlew quarkusDev

Once the application is exposed on port 8080 , run an http command:

http :8080/api/v1/klines

You should have a response like this:

http :8080/api/v1/klines
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
content-length: 841

[
    [
        1691506080000,
        "29534.00000000",
        "29534.00000000",
        "29515.03000000",
        "29515.04000000",
        "75.73496000",
        1691506139999,
        "2235902.73979500",
        1503,
        "32.63736000",
        "963563.15455500"
    ],
    [
...

The response represents the 5 one-minute candlestick bars that we requested. Each candlestick bar is represented by an array of values, such as the open price, the high price, the low price, the close price, the volume, the number of trades, and more.

Why Quarkus

One of the reasons why Quarkus is a great choice for the developer side is the hot-reload feature. This feature allows you to make changes to your code and see the results immediately, without having to restart your application or redeploy your artifacts. This saves you time and improves your productivity and feedback loop.

Thanks to JAX RS, you can use annotations to declare your endpoints, parameters, responses, and exceptions. Additionally, you can also use MicroProfile OpenAPI to generate and document your API specifications.

You can use annotations to define the interface of your REST client and let Quarkus generate the implementation for you. You can also configure various aspects of your REST client such as timeouts, headers, SSL and more. This simplifies your code and reduces boilerplate.