0

I'm discovering Armeria framework and I want to consume a REST service. Using the Armeria WebClient:

WebClient webClient = WebClient.of("http://localhost:9090");
RequestHeaders getJson = RequestHeaders.of(HttpMethod.GET, "/some-service",
            HttpHeaderNames.CONTENT_TYPE, "application/json", "SomeHeader", "armeriaTest");
return webClient.execute(getJson).aggregate().thenApply(resp->{
        if(HttpStatus.OK.equals(resp.status())) {
            return parseBody(resp.contentUtf8());
        }else if(HttpStatus.BAD_REQUEST.equals(resp.status())){
            throw new IllegalStateException("not exists");
        }
        throw new RuntimeException("Error");
    });

This code returns a CompletionStage that will be resolved asynchronously, because if I do a join() or get() right here causes an "java.lang.IllegalStateException: Blocking event loop, don't do this."

My question is: What if I want to use a third party httpclient library (like Apache HttpClient) instead the Web? The client call should be wrapped in a Future too? How should I manage the client requests to fit in the framework approach and avoid the "Blocking event loop" issue?

Thanks to all!

1 Answers1

0

Yes. You should never perform any blocking operations when your code is running in an event loop thread. You can perform a blocking operation by submitting it to other thread pool dedicated to handling blocking operations.

If you are using Armeria on the server side, you can get one via ServiceRequestContext.blockingTaskExecutor():

Server server = Server
    .builder()
    .service("/", (ctx, req) -> {
        CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
            // Perform some blocking operations that return a string.
        }, ctx.blockingTaskExecutor());

        CompletableFuture<String> f2 = f1.thenApply(result -> {
            // Transform the result into an HttpResponse.
            return HttpResponse.of("Result: %s", result);
        });

        return HttpResponse.from(f2);
    })
    .build();

If you are not using Armeria on the server side, you can use other Executor provided by your platform, or you can even create a new ThreadPoolExecutor dedicated to handling blocking operations.

trustin
  • 12,231
  • 6
  • 42
  • 52