Convert Figma logo to code with AI

AsyncHttpClient logoasync-http-client

Asynchronous Http and WebSocket Client library for Java

6,267
1,588
6,267
107

Top Related Projects

45,699

Square’s meticulous HTTP client for the JVM, Android, and GraalVM.

42,958

A type-safe HTTP client for Android and the JVM

Mirror of Apache HttpClient

14,240

Vert.x is a tool-kit for building reactive applications on the JVM

47,834

RxJava – Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM.

Spring Framework

Quick Overview

Async Http Client (AHC) is a high-performance, asynchronous HTTP client library for Java. It provides a simple and flexible API for making HTTP requests, supporting both synchronous and asynchronous operations, and is built on top of Netty for efficient network communication.

Pros

  • High performance and scalability due to its asynchronous nature
  • Supports both synchronous and asynchronous request handling
  • Extensive feature set, including WebSocket support, OAuth, and streaming
  • Flexible configuration options for fine-tuning performance

Cons

  • Steeper learning curve compared to simpler HTTP clients
  • Documentation could be more comprehensive and up-to-date
  • May be overkill for simple use cases or small projects
  • Requires careful management of resources in high-concurrency scenarios

Code Examples

  1. Making a simple GET request:
AsyncHttpClient client = Dsl.asyncHttpClient();
CompletableFuture<Response> future = client.prepareGet("http://example.com")
    .execute()
    .toCompletableFuture();
Response response = future.get();
System.out.println(response.getResponseBody());
client.close();
  1. Performing an asynchronous POST request:
AsyncHttpClient client = Dsl.asyncHttpClient();
client.preparePost("http://example.com/api")
    .setBody("{\"key\":\"value\"}")
    .setHeader("Content-Type", "application/json")
    .execute(new AsyncCompletionHandler<Response>() {
        @Override
        public Response onCompleted(Response response) throws Exception {
            System.out.println("Response: " + response.getResponseBody());
            return response;
        }
    });
client.close();
  1. Using WebSocket:
AsyncHttpClient client = Dsl.asyncHttpClient();
WebSocket websocket = client.prepareGet("ws://example.com/websocket")
    .execute(new WebSocketUpgradeHandler.Builder().addWebSocketListener(
        new WebSocketListener() {
            @Override
            public void onMessage(String message) {
                System.out.println("Received message: " + message);
            }
        }).build()).get();
websocket.sendMessage("Hello, WebSocket!");
client.close();

Getting Started

To use Async Http Client in your project, add the following dependency to your Maven pom.xml:

<dependency>
    <groupId>org.asynchttpclient</groupId>
    <artifactId>async-http-client</artifactId>
    <version>2.12.3</version>
</dependency>

For Gradle, add this to your build.gradle:

implementation 'org.asynchttpclient:async-http-client:2.12.3'

Then, you can start using the client in your Java code:

import org.asynchttpclient.*;
import static org.asynchttpclient.Dsl.*;

AsyncHttpClient client = asyncHttpClient();
// Use the client to make requests
// ...
client.close();

Competitor Comparisons

45,699

Square’s meticulous HTTP client for the JVM, Android, and GraalVM.

Pros of OkHttp

  • Simpler API and easier to use for basic HTTP requests
  • Better performance and lower memory footprint
  • More active development and frequent updates

Cons of OkHttp

  • Less flexible for advanced use cases and custom configurations
  • Limited support for WebSocket connections compared to async-http-client
  • Fewer built-in features for handling specific scenarios (e.g., OAuth)

Code Comparison

async-http-client:

AsyncHttpClient client = Dsl.asyncHttpClient();
Future<Response> f = client.prepareGet("http://www.example.com/").execute();
Response r = f.get();

OkHttp:

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
    .url("http://www.example.com/")
    .build();
Response response = client.newCall(request).execute();

Both libraries offer asynchronous HTTP client functionality for Java applications. async-http-client provides more advanced features and flexibility, making it suitable for complex scenarios. OkHttp, on the other hand, offers a simpler API and better performance for common use cases.

async-http-client excels in scenarios requiring fine-grained control over request execution and handling, while OkHttp is often preferred for its ease of use and efficiency in typical HTTP operations. The choice between the two depends on the specific requirements of your project and the level of control needed over HTTP communications.

42,958

A type-safe HTTP client for Android and the JVM

Pros of Retrofit

  • Simpler API design with annotation-based interface declarations
  • Built-in support for popular serialization libraries (e.g., Gson, Moshi)
  • Seamless integration with OkHttp for efficient networking

Cons of Retrofit

  • Less flexible for advanced use cases requiring fine-grained control
  • Limited to HTTP-based APIs, not suitable for other protocols
  • Steeper learning curve for developers new to annotation-based APIs

Code Comparison

Retrofit:

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

GitHubService service = retrofit.create(GitHubService.class);

async-http-client:

AsyncHttpClient client = new DefaultAsyncHttpClient();
client.prepareGet("https://api.github.com/users/user/repos")
    .execute()
    .toCompletableFuture()
    .thenAccept(response -> {
        // Handle response
    });

Summary

Retrofit offers a more declarative approach to API integration, making it easier to use for simple HTTP-based APIs. It provides built-in support for popular serialization libraries and integrates well with OkHttp. However, async-http-client offers more flexibility for advanced use cases and supports a wider range of protocols. The choice between the two depends on the specific requirements of your project and your preferred coding style.

Mirror of Apache HttpClient

Pros of httpcomponents-client

  • More mature and stable, with a longer history of development
  • Extensive documentation and wider community support
  • Supports both synchronous and asynchronous operations

Cons of httpcomponents-client

  • Generally considered less performant for high-concurrency scenarios
  • More verbose API, requiring more code for basic operations
  • Heavier dependency footprint

Code Comparison

httpcomponents-client:

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet request = new HttpGet("https://api.example.com/data");
CloseableHttpResponse response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);

async-http-client:

AsyncHttpClient client = Dsl.asyncHttpClient();
Future<Response> f = client.prepareGet("https://api.example.com/data").execute();
Response r = f.get();
String result = r.getResponseBody();

The async-http-client code is more concise and focuses on asynchronous operations by default. It provides a more streamlined API for handling HTTP requests and responses. On the other hand, httpcomponents-client offers more flexibility with both synchronous and asynchronous options, but requires more boilerplate code for basic operations.

Both libraries are widely used and have their strengths. The choice between them often depends on specific project requirements, performance needs, and developer preferences.

14,240

Vert.x is a tool-kit for building reactive applications on the JVM

Pros of vert.x

  • More comprehensive toolkit for building reactive applications
  • Supports multiple programming languages (polyglot)
  • Better suited for building full-stack applications

Cons of vert.x

  • Steeper learning curve due to its broader scope
  • May be overkill for simple HTTP client needs
  • Larger footprint and potentially higher resource usage

Code Comparison

vert.x HTTP client example:

WebClient client = WebClient.create(vertx);
client.get(8080, "localhost", "/")
  .send(ar -> {
    if (ar.succeeded()) {
      System.out.println("Got response: " + ar.result().bodyAsString());
    } else {
      System.out.println("Error: " + ar.cause().getMessage());
    }
  });

async-http-client example:

AsyncHttpClient client = Dsl.asyncHttpClient();
client.prepareGet("http://localhost:8080/")
  .execute(new AsyncCompletionHandler<Response>() {
    @Override
    public Response onCompleted(Response response) {
      System.out.println("Got response: " + response.getResponseBody());
      return response;
    }
  });

Both libraries provide asynchronous HTTP client functionality, but vert.x offers a more comprehensive toolkit for building reactive applications across multiple languages. async-http-client is more focused on providing a simple, efficient HTTP client for Java. vert.x may be better suited for larger, more complex projects, while async-http-client might be preferable for simpler use cases or when a lightweight HTTP client is needed.

47,834

RxJava – Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM.

Pros of RxJava

  • Comprehensive reactive programming framework with a wide range of operators
  • Supports multiple programming paradigms (functional, declarative, reactive)
  • Excellent for handling complex asynchronous operations and event streams

Cons of RxJava

  • Steeper learning curve due to its extensive API and concepts
  • Can be overkill for simple HTTP requests or basic asynchronous operations
  • Potential for memory leaks if not used correctly (e.g., unsubscribed Observables)

Code Comparison

RxJava example:

Observable.just("https://api.example.com/data")
    .flatMap(url -> Observable.fromCallable(() -> makeHttpRequest(url)))
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(response -> handleResponse(response), error -> handleError(error));

async-http-client example:

AsyncHttpClient client = new AsyncHttpClient();
client.prepareGet("https://api.example.com/data")
    .execute(new AsyncCompletionHandler<Response>() {
        @Override
        public Response onCompleted(Response response) throws Exception {
            handleResponse(response);
            return response;
        }
    });

Summary

RxJava is a powerful reactive programming library that excels in handling complex asynchronous operations and event streams. It offers a wide range of operators and supports multiple programming paradigms. However, it has a steeper learning curve and may be excessive for simple HTTP requests.

async-http-client, on the other hand, is more focused on providing asynchronous HTTP client functionality. It's simpler to use for basic HTTP operations but lacks the extensive reactive programming features of RxJava.

Choose RxJava for complex reactive programming needs, and async-http-client for straightforward asynchronous HTTP requests.

Spring Framework

Pros of Spring Framework

  • Comprehensive ecosystem with extensive features for web development, data access, and more
  • Strong community support and regular updates
  • Seamless integration with other Spring projects and third-party libraries

Cons of Spring Framework

  • Steeper learning curve due to its extensive feature set
  • Can be considered "heavyweight" for smaller projects
  • Configuration can be complex, especially for beginners

Code Comparison

Spring Framework (HTTP request):

RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("https://api.example.com/data", String.class);

Async HTTP Client:

AsyncHttpClient client = Dsl.asyncHttpClient();
Future<Response> f = client.prepareGet("https://api.example.com/data").execute();
Response r = f.get();

Summary

Spring Framework is a comprehensive Java application framework, while Async HTTP Client is specifically focused on asynchronous HTTP requests. Spring Framework offers a wider range of features and integrations but may be overkill for simple projects. Async HTTP Client provides a more lightweight solution for handling HTTP requests asynchronously, which can be beneficial for performance-critical applications. The choice between the two depends on the project's specific requirements and complexity.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Async Http Client

Build Maven Central

Follow @AsyncHttpClient on Twitter.

The AsyncHttpClient (AHC) library allows Java applications to easily execute HTTP requests and asynchronously process HTTP responses. The library also supports the WebSocket Protocol.

It's built on top of Netty. It's compiled with Java 11.

Installation

Binaries are deployed on Maven Central. Add a dependency on the main AsyncHttpClient artifact:

Maven:

<dependencies>
    <dependency>
        <groupId>org.asynchttpclient</groupId>
        <artifactId>async-http-client</artifactId>
        <version>3.0.0</version>
    </dependency>
</dependencies>

Gradle:

dependencies {
    implementation 'org.asynchttpclient:async-http-client:3.0.0'
}

Dsl

Import the Dsl helpers to use convenient methods to bootstrap components:

import static org.asynchttpclient.Dsl.*;

Client

import static org.asynchttpclient.Dsl.*;

AsyncHttpClient asyncHttpClient=asyncHttpClient();

AsyncHttpClient instances must be closed (call the close method) once you're done with them, typically when shutting down your application. If you don't, you'll experience threads hanging and resource leaks.

AsyncHttpClient instances are intended to be global resources that share the same lifecycle as the application. Typically, AHC will usually underperform if you create a new client for each request, as it will create new threads and connection pools for each. It's possible to create shared resources (EventLoop and Timer) beforehand and pass them to multiple client instances in the config. You'll then be responsible for closing those shared resources.

Configuration

Finally, you can also configure the AsyncHttpClient instance via its AsyncHttpClientConfig object:

import static org.asynchttpclient.Dsl.*;

AsyncHttpClient c=asyncHttpClient(config().setProxyServer(proxyServer("127.0.0.1",38080)));

HTTP

Sending Requests

Basics

AHC provides 2 APIs for defining requests: bound and unbound. AsyncHttpClient and Dsl` provide methods for standard HTTP methods (POST, PUT, etc) but you can also pass a custom one.

import org.asynchttpclient.*;

// bound
Future<Response> whenResponse=asyncHttpClient.prepareGet("http://www.example.com/").execute();

// unbound
        Request request=get("http://www.example.com/").build();
        Future<Response> whenResponse=asyncHttpClient.executeRequest(request);

Setting Request Body

Use the setBody method to add a body to the request.

This body can be of type:

  • java.io.File
  • byte[]
  • List<byte[]>
  • String
  • java.nio.ByteBuffer
  • java.io.InputStream
  • Publisher<io.netty.buffer.ByteBuf>
  • org.asynchttpclient.request.body.generator.BodyGenerator

BodyGenerator is a generic abstraction that let you create request bodies on the fly. Have a look at FeedableBodyGenerator if you're looking for a way to pass requests chunks on the fly.

Multipart

Use the addBodyPart method to add a multipart part to the request.

This part can be of type:

  • ByteArrayPart
  • FilePart
  • InputStreamPart
  • StringPart

Dealing with Responses

Blocking on the Future

execute methods return a java.util.concurrent.Future. You can simply block the calling thread to get the response.

Future<Response> whenResponse=asyncHttpClient.prepareGet("http://www.example.com/").execute();
        Response response=whenResponse.get();

This is useful for debugging but you'll most likely hurt performance or create bugs when running such code on production. The point of using a non blocking client is to NOT BLOCK the calling thread!

Setting callbacks on the ListenableFuture

execute methods actually return a org.asynchttpclient.ListenableFuture similar to Guava's. You can configure listeners to be notified of the Future's completion.

        ListenableFuture<Response> whenResponse = ???;
        Runnable callback = () - > {
            try {
               Response response = whenResponse.get();
               System.out.println(response);
            } catch (InterruptedException | ExecutionException e) {
               e.printStackTrace();
            }
        };

        java.util.concurrent.Executor executor = ???;
        whenResponse.addListener(() - > ??? , executor);

If the executor parameter is null, callback will be executed in the IO thread. You MUST NEVER PERFORM BLOCKING operations in there, typically sending another request and block on a future.

Using custom AsyncHandlers

execute methods can take an org.asynchttpclient.AsyncHandler to be notified on the different events, such as receiving the status, the headers and body chunks. When you don't specify one, AHC will use a org.asynchttpclient.AsyncCompletionHandler;

AsyncHandler methods can let you abort processing early (return AsyncHandler.State.ABORT) and can let you return a computation result from onCompleted that will be used as the Future's result. See AsyncCompletionHandler implementation as an example.

The below sample just capture the response status and skips processing the response body chunks.

Note that returning ABORT closes the underlying connection.

import static org.asynchttpclient.Dsl.*;

import org.asynchttpclient.*;
import io.netty.handler.codec.http.HttpHeaders;

Future<Integer> whenStatusCode = asyncHttpClient.prepareGet("http://www.example.com/")
        .execute(new AsyncHandler<Integer> () {
            private Integer status;
            
            @Override
            public State onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
                status = responseStatus.getStatusCode();
                return State.ABORT;
            }
            
            @Override
            public State onHeadersReceived(HttpHeaders headers) throws Exception {
              return State.ABORT;
            }
            
            @Override
            public State onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
                 return State.ABORT;
            }
        
            @Override
            public Integer onCompleted() throws Exception{
                return status;
            }
        
            @Override
            public void onThrowable(Throwable t) {
                t.printStackTrace();
            }
        });

        Integer statusCode = whenStatusCode.get();

Using Continuations

ListenableFuture has a toCompletableFuture method that returns a CompletableFuture. Beware that canceling this CompletableFuture won't properly cancel the ongoing request. There's a very good chance we'll return a CompletionStage instead in the next release.

CompletableFuture<Response> whenResponse=asyncHttpClient
        .prepareGet("http://www.example.com/")
        .execute()
        .toCompletableFuture()
        .exceptionally(t->{ /* Something wrong happened... */  })
        .thenApply(response->{ /*  Do something with the Response */ return resp;});
        whenResponse.join(); // wait for completion

You may get the complete maven project for this simple demo from org.asynchttpclient.example

WebSocket

Async Http Client also supports WebSocket. You need to pass a WebSocketUpgradeHandler where you would register a WebSocketListener.

WebSocket websocket = c.prepareGet("ws://demos.kaazing.com/echo")
        .execute(new WebSocketUpgradeHandler.Builder().addWebSocketListener(
                new WebSocketListener() {

                  @Override
                  public void onOpen(WebSocket websocket) {
                    websocket.sendTextFrame("...").sendTextFrame("...");
                  }

                  @Override
                  public void onClose(WebSocket websocket) {
                    // ...
                  }

                  @Override
                  public void onTextFrame(String payload, boolean finalFragment, int rsv) {
                    System.out.println(payload);
                  }

                  @Override
                  public void onError(Throwable t) {
                    t.printStackTrace();
                  }
                }).build()).get();

User Group

Keep up to date on the library development by joining the Asynchronous HTTP Client discussion group

GitHub Discussions