CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-apache-httpcomponents--fluent-hc

Apache HttpComponents Client fluent API providing a simplified interface for HTTP operations

Pending
Overview
Eval results
Files

async-operations.mddocs/

Asynchronous Operations

The Async class provides asynchronous execution of HTTP requests using Future-based patterns with optional callback support. Requests are executed in background threads while allowing the main thread to continue processing.

Async Instance Creation

Create Async instances using the static factory method:

public static Async newInstance();

Usage Examples

import org.apache.http.client.fluent.Async;

Async async = Async.newInstance();

Configuration

Configure the Async instance with custom executors:

public Async use(Executor executor);
public Async use(java.util.concurrent.Executor concurrentExec);

Usage Examples

import org.apache.http.client.fluent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

// Use custom HTTP executor for authentication/cookies
Executor httpExecutor = Executor.newInstance()
    .auth("api.example.com", "username", "password");

// Use custom thread pool for concurrent execution
ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);

Async async = Async.newInstance()
    .use(httpExecutor)           // HTTP context management
    .use(threadPool);            // Thread execution

Asynchronous Execution Methods

Execute requests asynchronously with various response handling options:

public <T> Future<T> execute(Request request, ResponseHandler<T> handler);
public <T> Future<T> execute(Request request, ResponseHandler<T> handler, FutureCallback<T> callback);
public Future<Content> execute(Request request);
public Future<Content> execute(Request request, FutureCallback<Content> callback);

Basic Async Execution

Execute requests returning Future objects:

import org.apache.http.client.fluent.Request;
import org.apache.http.client.fluent.Content;
import java.util.concurrent.Future;

Async async = Async.newInstance();

// Simple async execution returning Content
Future<Content> future = async.execute(Request.Get("https://api.example.com/data"));

// Block and get result
Content content = future.get();
String response = content.asString();

// Non-blocking check
if (future.isDone()) {
    Content result = future.get();
}

Custom Response Handlers

Use custom ResponseHandler for specific response processing:

import org.apache.http.client.ResponseHandler;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import java.util.concurrent.Future;

// Custom handler to extract status code
ResponseHandler<Integer> statusHandler = new ResponseHandler<Integer>() {
    @Override
    public Integer handleResponse(HttpResponse response) {
        return response.getStatusLine().getStatusCode();
    }
};

// Execute with custom handler
Future<Integer> statusFuture = async.execute(
    Request.Get("https://api.example.com/check"), 
    statusHandler
);

Integer statusCode = statusFuture.get();
System.out.println("Status: " + statusCode);

Callback-based Execution

Use callbacks for asynchronous result processing:

import org.apache.http.concurrent.FutureCallback;
import java.util.concurrent.Future;

// Callback for Content results
FutureCallback<Content> contentCallback = new FutureCallback<Content>() {
    @Override
    public void completed(Content result) {
        System.out.println("Request completed: " + result.asString());
    }

    @Override
    public void failed(Exception ex) {
        System.err.println("Request failed: " + ex.getMessage());
    }

    @Override
    public void cancelled() {
        System.out.println("Request cancelled");
    }
};

// Execute with callback
Future<Content> future = async.execute(
    Request.Get("https://api.example.com/data"), 
    contentCallback
);

// Continue with other work while request executes in background
doOtherWork();

// Optionally wait for completion
future.get();

Multiple Concurrent Requests

Execute multiple requests concurrently:

import java.util.concurrent.Future;
import java.util.List;
import java.util.ArrayList;

Async async = Async.newInstance();
List<Future<Content>> futures = new ArrayList<>();

// Start multiple async requests
futures.add(async.execute(Request.Get("https://api.example.com/data1")));
futures.add(async.execute(Request.Get("https://api.example.com/data2")));
futures.add(async.execute(Request.Get("https://api.example.com/data3")));

// Process results as they complete
for (Future<Content> future : futures) {
    Content content = future.get(); // Blocks until this specific request completes
    System.out.println("Response: " + content.asString());
}

Future Operations

The returned Future objects support standard Future interface operations:

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

Future<Content> future = async.execute(Request.Get("https://slow-api.example.com/data"));

// Check if completed
boolean done = future.isDone();

// Cancel if not started or interrupt if running
boolean cancelled = future.cancel(true);

// Get with timeout
try {
    Content content = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException e) {
    System.err.println("Request timed out");
    future.cancel(true);
}

Error Handling

Async operations can fail in various ways:

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

Future<Content> future = async.execute(Request.Get("https://api.example.com/data"));

try {
    Content content = future.get();
    String response = content.asString();
} catch (ExecutionException e) {
    // Unwrap the actual exception
    Throwable cause = e.getCause();
    if (cause instanceof IOException) {
        System.err.println("I/O error: " + cause.getMessage());
    } else if (cause instanceof ClientProtocolException) {
        System.err.println("Protocol error: " + cause.getMessage());
    } else {
        System.err.println("Unexpected error: " + cause.getMessage());
    }
} catch (InterruptedException e) {
    System.err.println("Request interrupted: " + e.getMessage());
    Thread.currentThread().interrupt();
}

Advanced Patterns

Async with Authentication

Combine Async with Executor for authenticated requests:

import org.apache.http.client.fluent.Executor;

// Create authenticated executor
Executor authenticatedExecutor = Executor.newInstance()
    .auth("api.example.com", "username", "password");

// Use with async
Async async = Async.newInstance()
    .use(authenticatedExecutor);

// All async requests will be authenticated
Future<Content> future = async.execute(Request.Get("https://api.example.com/private-data"));

Async with Custom Thread Pool

Use a managed thread pool for better resource control:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

ExecutorService threadPool = Executors.newFixedThreadPool(5);

Async async = Async.newInstance()
    .use(threadPool);

// Execute multiple requests using the managed thread pool
List<Future<Content>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
    futures.add(async.execute(Request.Get("https://api.example.com/data/" + i)));
}

// Process results
for (Future<Content> future : futures) {
    Content content = future.get();
    System.out.println("Response: " + content.asString());
}

// Clean up
threadPool.shutdown();

Async with Progress Tracking

Track progress of multiple async operations:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;

Async async = Async.newInstance();
AtomicInteger completed = new AtomicInteger(0);
AtomicInteger total = new AtomicInteger(5);

FutureCallback<Content> progressCallback = new FutureCallback<Content>() {
    @Override
    public void completed(Content result) {
        int count = completed.incrementAndGet();
        System.out.println("Progress: " + count + "/" + total.get());
    }

    @Override
    public void failed(Exception ex) {
        System.err.println("Request failed: " + ex.getMessage());
        completed.incrementAndGet(); // Count failures too
    }

    @Override
    public void cancelled() {
        System.out.println("Request cancelled");
        completed.incrementAndGet(); // Count cancellations too
    }
};

// Start requests with progress tracking
for (int i = 0; i < total.get(); i++) {
    async.execute(Request.Get("https://api.example.com/data/" + i), progressCallback);
}

Thread Safety

The Async class is thread-safe and can be used concurrently from multiple threads. However, each execution creates a new background thread or uses the configured thread pool.

Best Practices

  1. Reuse Async instances: Create once and reuse for multiple requests
  2. Configure thread pools: Use custom ExecutorService for better resource management
  3. Handle timeouts: Always use timeout when calling future.get()
  4. Combine with Executor: Use Executor for authentication/session management
  5. Process failures: Always handle ExecutionException in Future.get()
  6. Clean up resources: Shutdown custom thread pools when done

Complete Example

import org.apache.http.client.fluent.*;
import org.apache.http.concurrent.FutureCallback;
import java.util.concurrent.*;
import java.util.List;
import java.util.ArrayList;

public class AsyncExample {
    public static void main(String[] args) {
        // Custom thread pool
        ExecutorService threadPool = Executors.newFixedThreadPool(3);
        
        // Authenticated HTTP executor
        Executor httpExecutor = Executor.newInstance()
            .auth("api.example.com", "username", "password");
        
        // Async with custom configuration
        Async async = Async.newInstance()
            .use(httpExecutor)
            .use(threadPool);
        
        try {
            // Multiple concurrent requests
            List<Future<Content>> futures = new ArrayList<>();
            
            futures.add(async.execute(Request.Get("https://api.example.com/users")));
            futures.add(async.execute(Request.Get("https://api.example.com/orders")));
            futures.add(async.execute(Request.Get("https://api.example.com/products")));
            
            // Process results with timeout
            for (Future<Content> future : futures) {
                try {
                    Content content = future.get(10, TimeUnit.SECONDS);
                    System.out.println("Response length: " + content.asBytes().length);
                } catch (TimeoutException e) {
                    System.err.println("Request timed out");
                    future.cancel(true);
                } catch (ExecutionException e) {
                    System.err.println("Request failed: " + e.getCause().getMessage());
                }
            }
            
        } catch (InterruptedException e) {
            System.err.println("Interrupted: " + e.getMessage());
            Thread.currentThread().interrupt();
        } finally {
            // Clean up resources
            threadPool.shutdown();
            Executor.closeIdleConnections();
        }
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-apache-httpcomponents--fluent-hc

docs

async-operations.md

executor-auth.md

index.md

request-operations.md

response-handling.md

tile.json