Skip to content

Commit baf191b

Browse files
committed
Add Async list() of beans support
1 parent 24704fb commit baf191b

File tree

4 files changed

+69
-4
lines changed

4 files changed

+69
-4
lines changed

client/src/main/java/io/avaje/http/client/DHttpAsync.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.avaje.http.client;
22

33
import java.net.http.HttpResponse;
4+
import java.util.List;
45
import java.util.concurrent.CompletableFuture;
56

67
class DHttpAsync implements HttpAsyncResponse {
@@ -31,4 +32,11 @@ public <E> CompletableFuture<E> bean(Class<E> type) {
3132
.performSendAsync(true, HttpResponse.BodyHandlers.ofByteArray())
3233
.thenApply(httpResponse -> request.asyncBean(type, httpResponse));
3334
}
35+
36+
@Override
37+
public <E> CompletableFuture<List<E>> list(Class<E> type) {
38+
return request
39+
.performSendAsync(true, HttpResponse.BodyHandlers.ofByteArray())
40+
.thenApply(httpResponse -> request.asyncList(type, httpResponse));
41+
}
3442
}

client/src/main/java/io/avaje/http/client/DHttpClientRequest.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,15 +394,24 @@ protected <T> CompletableFuture<HttpResponse<T>> performSendAsync(boolean loggab
394394
}
395395

396396
protected <E> E asyncBean(Class<E> type, HttpResponse<byte[]> response) {
397+
afterAsyncEncoded(response);
398+
return context.readBean(type, encodedResponseBody);
399+
}
400+
401+
protected <E> List<E> asyncList(Class<E> type, HttpResponse<byte[]> response) {
402+
afterAsyncEncoded(response);
403+
return context.readList(type, encodedResponseBody);
404+
}
405+
406+
private void afterAsyncEncoded(HttpResponse<byte[]> response) {
397407
requestTimeNanos = System.nanoTime() - startAsyncNanos;
398408
httpResponse = response;
399409
encodedResponseBody = context.readContent(response);
400410
context.afterResponse(this);
401411
context.checkMaybeThrow(response);
402-
return context.readBean(type, encodedResponseBody);
403412
}
404413

405-
public <E> HttpResponse<E> afterAsync(HttpResponse<E> response) {
414+
protected <E> HttpResponse<E> afterAsync(HttpResponse<E> response) {
406415
requestTimeNanos = System.nanoTime() - startAsyncNanos;
407416
httpResponse = response;
408417
context.afterResponse(this);

client/src/main/java/io/avaje/http/client/HttpAsyncResponse.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.avaje.http.client;
22

33
import java.net.http.HttpResponse;
4+
import java.util.List;
45
import java.util.concurrent.CompletableFuture;
56

67
/**
@@ -81,11 +82,37 @@ public interface HttpAsyncResponse {
8182
* // use helloDto
8283
* ...
8384
* }
84-
*
8585
* });
86+
* }</pre>
87+
*/
88+
<E> CompletableFuture<E> bean(Class<E> type);
89+
90+
/**
91+
* Process expecting a list of beans response body (typically from json content).
92+
* <p>
93+
* If the HTTP statusCode is 300 or above a HttpException is throw which
94+
* contains the HttpResponse.
95+
*
96+
* <pre>{@code
97+
*
98+
* clientContext.request()
99+
* ...
100+
* .GET().async()
101+
* .list(HelloDto.class)
102+
* .whenComplete((helloDtos, throwable) -> {
86103
*
104+
* if (throwable != null) {
105+
* HttpException httpException = (HttpException) throwable.getCause();
106+
* int statusCode = httpException.getStatusCode();
107+
* ...
87108
*
109+
* } else {
110+
* // use list of helloDto
111+
* ...
112+
* }
113+
* });
88114
* }</pre>
89115
*/
90-
<E> CompletableFuture<E> bean(Class<E> type);
116+
<E> CompletableFuture<List<E>> list(Class<E> type);
117+
91118
}

client/src/test/java/io/avaje/http/client/HelloControllerTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,27 @@ void get_hello_returningListOfBeans() {
104104
assertThat(helloDtos).hasSize(2);
105105
}
106106

107+
@Test
108+
void async_list() throws ExecutionException, InterruptedException {
109+
110+
AtomicReference<List<HelloDto>> ref = new AtomicReference<>();
111+
112+
final CompletableFuture<List<HelloDto>> future = clientContext.request()
113+
.path("hello")
114+
.GET().async()
115+
.list(HelloDto.class);
116+
117+
future.whenComplete((helloDtos, throwable) -> {
118+
assertThat(throwable).isNull();
119+
assertThat(helloDtos).hasSize(2);
120+
ref.set(helloDtos);
121+
});
122+
123+
final List<HelloDto> helloDtos = future.get();
124+
assertThat(helloDtos).hasSize(2);
125+
assertThat(helloDtos).isSameAs(ref.get());
126+
}
127+
107128
@Test
108129
void get_withPathParamAndQueryParam_returningBean() {
109130

0 commit comments

Comments
 (0)