or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-operations.mdexecutor-auth.mdindex.mdrequest-operations.mdresponse-handling.md

async-operations.mddocs/

0

# Asynchronous Operations

1

2

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.

3

4

## Async Instance Creation

5

6

Create Async instances using the static factory method:

7

8

```java { .api }

9

public static Async newInstance();

10

```

11

12

### Usage Examples

13

14

```java

15

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

16

17

Async async = Async.newInstance();

18

```

19

20

## Configuration

21

22

Configure the Async instance with custom executors:

23

24

```java { .api }

25

public Async use(Executor executor);

26

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

27

```

28

29

### Usage Examples

30

31

```java

32

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

33

import java.util.concurrent.Executors;

34

import java.util.concurrent.ThreadPoolExecutor;

35

36

// Use custom HTTP executor for authentication/cookies

37

Executor httpExecutor = Executor.newInstance()

38

.auth("api.example.com", "username", "password");

39

40

// Use custom thread pool for concurrent execution

41

ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);

42

43

Async async = Async.newInstance()

44

.use(httpExecutor) // HTTP context management

45

.use(threadPool); // Thread execution

46

```

47

48

## Asynchronous Execution Methods

49

50

Execute requests asynchronously with various response handling options:

51

52

```java { .api }

53

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

54

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

55

public Future<Content> execute(Request request);

56

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

57

```

58

59

### Basic Async Execution

60

61

Execute requests returning Future objects:

62

63

```java

64

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

65

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

66

import java.util.concurrent.Future;

67

68

Async async = Async.newInstance();

69

70

// Simple async execution returning Content

71

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

72

73

// Block and get result

74

Content content = future.get();

75

String response = content.asString();

76

77

// Non-blocking check

78

if (future.isDone()) {

79

Content result = future.get();

80

}

81

```

82

83

### Custom Response Handlers

84

85

Use custom ResponseHandler for specific response processing:

86

87

```java

88

import org.apache.http.client.ResponseHandler;

89

import org.apache.http.HttpResponse;

90

import org.apache.http.util.EntityUtils;

91

import java.util.concurrent.Future;

92

93

// Custom handler to extract status code

94

ResponseHandler<Integer> statusHandler = new ResponseHandler<Integer>() {

95

@Override

96

public Integer handleResponse(HttpResponse response) {

97

return response.getStatusLine().getStatusCode();

98

}

99

};

100

101

// Execute with custom handler

102

Future<Integer> statusFuture = async.execute(

103

Request.Get("https://api.example.com/check"),

104

statusHandler

105

);

106

107

Integer statusCode = statusFuture.get();

108

System.out.println("Status: " + statusCode);

109

```

110

111

### Callback-based Execution

112

113

Use callbacks for asynchronous result processing:

114

115

```java

116

import org.apache.http.concurrent.FutureCallback;

117

import java.util.concurrent.Future;

118

119

// Callback for Content results

120

FutureCallback<Content> contentCallback = new FutureCallback<Content>() {

121

@Override

122

public void completed(Content result) {

123

System.out.println("Request completed: " + result.asString());

124

}

125

126

@Override

127

public void failed(Exception ex) {

128

System.err.println("Request failed: " + ex.getMessage());

129

}

130

131

@Override

132

public void cancelled() {

133

System.out.println("Request cancelled");

134

}

135

};

136

137

// Execute with callback

138

Future<Content> future = async.execute(

139

Request.Get("https://api.example.com/data"),

140

contentCallback

141

);

142

143

// Continue with other work while request executes in background

144

doOtherWork();

145

146

// Optionally wait for completion

147

future.get();

148

```

149

150

### Multiple Concurrent Requests

151

152

Execute multiple requests concurrently:

153

154

```java

155

import java.util.concurrent.Future;

156

import java.util.List;

157

import java.util.ArrayList;

158

159

Async async = Async.newInstance();

160

List<Future<Content>> futures = new ArrayList<>();

161

162

// Start multiple async requests

163

futures.add(async.execute(Request.Get("https://api.example.com/data1")));

164

futures.add(async.execute(Request.Get("https://api.example.com/data2")));

165

futures.add(async.execute(Request.Get("https://api.example.com/data3")));

166

167

// Process results as they complete

168

for (Future<Content> future : futures) {

169

Content content = future.get(); // Blocks until this specific request completes

170

System.out.println("Response: " + content.asString());

171

}

172

```

173

174

## Future Operations

175

176

The returned Future objects support standard Future interface operations:

177

178

```java

179

import java.util.concurrent.Future;

180

import java.util.concurrent.TimeUnit;

181

import java.util.concurrent.TimeoutException;

182

183

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

184

185

// Check if completed

186

boolean done = future.isDone();

187

188

// Cancel if not started or interrupt if running

189

boolean cancelled = future.cancel(true);

190

191

// Get with timeout

192

try {

193

Content content = future.get(5, TimeUnit.SECONDS);

194

} catch (TimeoutException e) {

195

System.err.println("Request timed out");

196

future.cancel(true);

197

}

198

```

199

200

## Error Handling

201

202

Async operations can fail in various ways:

203

204

```java

205

import java.util.concurrent.ExecutionException;

206

import java.util.concurrent.Future;

207

208

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

209

210

try {

211

Content content = future.get();

212

String response = content.asString();

213

} catch (ExecutionException e) {

214

// Unwrap the actual exception

215

Throwable cause = e.getCause();

216

if (cause instanceof IOException) {

217

System.err.println("I/O error: " + cause.getMessage());

218

} else if (cause instanceof ClientProtocolException) {

219

System.err.println("Protocol error: " + cause.getMessage());

220

} else {

221

System.err.println("Unexpected error: " + cause.getMessage());

222

}

223

} catch (InterruptedException e) {

224

System.err.println("Request interrupted: " + e.getMessage());

225

Thread.currentThread().interrupt();

226

}

227

```

228

229

## Advanced Patterns

230

231

### Async with Authentication

232

233

Combine Async with Executor for authenticated requests:

234

235

```java

236

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

237

238

// Create authenticated executor

239

Executor authenticatedExecutor = Executor.newInstance()

240

.auth("api.example.com", "username", "password");

241

242

// Use with async

243

Async async = Async.newInstance()

244

.use(authenticatedExecutor);

245

246

// All async requests will be authenticated

247

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

248

```

249

250

### Async with Custom Thread Pool

251

252

Use a managed thread pool for better resource control:

253

254

```java

255

import java.util.concurrent.ExecutorService;

256

import java.util.concurrent.Executors;

257

258

ExecutorService threadPool = Executors.newFixedThreadPool(5);

259

260

Async async = Async.newInstance()

261

.use(threadPool);

262

263

// Execute multiple requests using the managed thread pool

264

List<Future<Content>> futures = new ArrayList<>();

265

for (int i = 0; i < 10; i++) {

266

futures.add(async.execute(Request.Get("https://api.example.com/data/" + i)));

267

}

268

269

// Process results

270

for (Future<Content> future : futures) {

271

Content content = future.get();

272

System.out.println("Response: " + content.asString());

273

}

274

275

// Clean up

276

threadPool.shutdown();

277

```

278

279

### Async with Progress Tracking

280

281

Track progress of multiple async operations:

282

283

```java

284

import java.util.concurrent.CompletableFuture;

285

import java.util.concurrent.atomic.AtomicInteger;

286

287

Async async = Async.newInstance();

288

AtomicInteger completed = new AtomicInteger(0);

289

AtomicInteger total = new AtomicInteger(5);

290

291

FutureCallback<Content> progressCallback = new FutureCallback<Content>() {

292

@Override

293

public void completed(Content result) {

294

int count = completed.incrementAndGet();

295

System.out.println("Progress: " + count + "/" + total.get());

296

}

297

298

@Override

299

public void failed(Exception ex) {

300

System.err.println("Request failed: " + ex.getMessage());

301

completed.incrementAndGet(); // Count failures too

302

}

303

304

@Override

305

public void cancelled() {

306

System.out.println("Request cancelled");

307

completed.incrementAndGet(); // Count cancellations too

308

}

309

};

310

311

// Start requests with progress tracking

312

for (int i = 0; i < total.get(); i++) {

313

async.execute(Request.Get("https://api.example.com/data/" + i), progressCallback);

314

}

315

```

316

317

## Thread Safety

318

319

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.

320

321

## Best Practices

322

323

1. **Reuse Async instances**: Create once and reuse for multiple requests

324

2. **Configure thread pools**: Use custom ExecutorService for better resource management

325

3. **Handle timeouts**: Always use timeout when calling `future.get()`

326

4. **Combine with Executor**: Use Executor for authentication/session management

327

5. **Process failures**: Always handle ExecutionException in Future.get()

328

6. **Clean up resources**: Shutdown custom thread pools when done

329

330

## Complete Example

331

332

```java

333

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

334

import org.apache.http.concurrent.FutureCallback;

335

import java.util.concurrent.*;

336

import java.util.List;

337

import java.util.ArrayList;

338

339

public class AsyncExample {

340

public static void main(String[] args) {

341

// Custom thread pool

342

ExecutorService threadPool = Executors.newFixedThreadPool(3);

343

344

// Authenticated HTTP executor

345

Executor httpExecutor = Executor.newInstance()

346

.auth("api.example.com", "username", "password");

347

348

// Async with custom configuration

349

Async async = Async.newInstance()

350

.use(httpExecutor)

351

.use(threadPool);

352

353

try {

354

// Multiple concurrent requests

355

List<Future<Content>> futures = new ArrayList<>();

356

357

futures.add(async.execute(Request.Get("https://api.example.com/users")));

358

futures.add(async.execute(Request.Get("https://api.example.com/orders")));

359

futures.add(async.execute(Request.Get("https://api.example.com/products")));

360

361

// Process results with timeout

362

for (Future<Content> future : futures) {

363

try {

364

Content content = future.get(10, TimeUnit.SECONDS);

365

System.out.println("Response length: " + content.asBytes().length);

366

} catch (TimeoutException e) {

367

System.err.println("Request timed out");

368

future.cancel(true);

369

} catch (ExecutionException e) {

370

System.err.println("Request failed: " + e.getCause().getMessage());

371

}

372

}

373

374

} catch (InterruptedException e) {

375

System.err.println("Interrupted: " + e.getMessage());

376

Thread.currentThread().interrupt();

377

} finally {

378

// Clean up resources

379

threadPool.shutdown();

380

Executor.closeIdleConnections();

381

}

382

}

383

}

384

```