Calling a Thrift service

Let’s assume we have the following Thrift IDL, served at, just like what we used in Running a Thrift service:

namespace java com.example.thrift.hello

service HelloService {
    string hello(1:string name)

Making a call starts from creating a client:

import com.linecorp.armeria.client.Clients;

HelloService.Iface helloService = Clients.newClient(
        HelloService.Iface.class); // or AsyncIface.class

String greeting = helloService.hello("Armerian World");
assert greeting.equals("Hello, Armerian World!");

Note that we added the serialization format of the call using the + operator in the scheme part of the URI. Because we are calling a Thrift server, we should choose: tbinary, tcompact, tjson or ttext.

Since we specified HelloService.Iface as the client type, Clients.newClient() will return a synchronous client implementation. If we specified HelloService.AsyncIface, the calling code would have looked like the following:

import com.linecorp.armeria.common.thrift.ThriftCompletableFuture;
import com.linecorp.armeria.common.util.CompletionActions;
import com.linecorp.armeria.client.Clients;

HelloService.AsyncIface helloService = Clients.newClient(

ThriftCompletableFuture<String> future = new ThriftCompletableFuture<String>();
helloService.hello("Armerian World", future);

future.thenAccept(response -> assert response.equals("Hello, Armerian World!"))
      .exceptionally(cause -> {
          return null;

The example above introduces a new class called ThriftCompletableFuture. It is a subtype of Java 8 CompletableFuture that implements Thrift AsyncMethodCallback. Once passed as a callback of an asynchronous Thrift call, ThriftCompletableFuture will complete itself when the reply is received or the call fails. You’ll find it way more convenient to consume the reply than AsyncMethodCallback thanks to the rich set of methods provided by CompletableFuture.

You can also use the builder pattern for client construction:

import com.linecorp.armeria.common.http.HttpRequest;
import com.linecorp.armeria.common.http.HttpResponse;

HelloService.Iface helloService = new ClientBuilder("tbinary+")
        .decorator(HttpRequest.class, HttpResponse.class, LoggingClient::new)
        .build(HelloService.Iface.class); // or AsyncIface.class

String greeting = helloService.hello("Armerian World");
assert greeting.equals("Hello, Armerian World!");

As you might have noticed already, we decorated the client using LoggingClient, which logs all requests and responses. You might be interested in decorating a client using other decorators, for example to gather metrics. Please also refer to ClientBuilder for more configuration options.