Testing and .join()
Note that when testing with async requests we frequently use .join()
on the CompletableFuture
such that the main thread waits for the async
processing to complete. After that various asserts can run knowing that the
async callback code has been executed.
Example using .join() for testing purposes
client.request()
...
.POST().async()
.bean(HelloDto.class)
.whenComplete((helloDto, throwable) -> {
...
}).join(); // wait for async processing to complete
// can assert now ...
assertThat(...)
Example async().bean()
In this example POST async that will return a bean converted from json response.
client.request()
...
.POST().async()
.bean(HelloDto.class)
.whenComplete((helloDto, throwable) -> {
if (throwable != null) {
HttpException httpException = (HttpException) throwable.getCause();
int statusCode = httpException.statusCode();
// maybe convert json error response body to a bean (using Jackson/Gson)
MyErrorBean errorResponse = httpException.bean(MyErrorBean.class);
..
} else {
// process helloDto
...
}
});
-
Method Summary
Modifier and TypeMethodDescription<E> CompletableFuture
<HttpResponse<E>> Process converting the response body to the given type.<E> CompletableFuture
<HttpResponse<E>> The same asas(Class)
but using a generic type.CompletableFuture
<HttpResponse<byte[]>> Process as response HttpResponse<byte[]>.Process discarding response body as HttpResponse<Void>.Process as response HttpResponse<InputStream>.asLines()
Process as response HttpResponse<Stream<String>>.<E> CompletableFuture
<HttpResponse<List<E>>> Process converting the response body to a list of the given type.<E> CompletableFuture
<HttpResponse<List<E>>> The same asasList(Class)
but using a generic type.<E> CompletableFuture
<HttpResponse<Stream<E>>> Process converting the response body to a stream of the given type.<E> CompletableFuture
<HttpResponse<Stream<E>>> The same asasStream(Class)
but using a generic type.asString()
Process as String response body HttpResponse<String>.asVoid()
Process the response with check for 200 range status code returning as HttpResponse<Void>.<E> CompletableFuture
<E> Process expecting a bean response body (typically from json content).<E> CompletableFuture
<E> Process expecting a bean response body (typically from json content).<E> CompletableFuture
<HttpResponse<E>> handler
(HttpResponse.BodyHandler<E> bodyHandler) Process with any givenHttpResponse.BodyHandler
.<E> CompletableFuture
<List<E>> Process expecting a list of beans response body (typically from json content).<E> CompletableFuture
<List<E>> Process expecting a list of beans response body (typically from json content).<E> CompletableFuture
<Stream<E>> Process response as a stream of beans (x-json-stream).<E> CompletableFuture
<Stream<E>> Process response as a stream of beans (x-json-stream).
-
Method Details
-
asVoid
CompletableFuture<HttpResponse<Void>> asVoid()Process the response with check for 200 range status code returning as HttpResponse<Void>.Unlike
asDiscarding()
this request will read any response content as bytes with the view that the response content can be an error message that could be read via for exampleHttpException.bean(Class)
.Will throw an HttpException if the status code is in the error range allowing the caller to access the error message body via for example
HttpException.bean(Class)
This is intended to be used for POST, PUT, DELETE requests where the caller is only interested in the response body when an error occurs (status code not in 200 range).
client.request() .path("hello/world") .GET() .async().asVoid() .whenComplete((hres, throwable) -> { if (throwable != null) { // if throwable.getCause() is a HttpException for status code >= 300 HttpException httpException = (HttpException) throwable.getCause(); int status = httpException.statusCode(); // convert json error response body to a bean ErrorResponse errorResponse = httpException.bean(ErrorResponse.class); ... } else { int statusCode = hres.statusCode(); ... } });
-
asDiscarding
CompletableFuture<HttpResponse<Void>> asDiscarding()Process discarding response body as HttpResponse<Void>.Unlike
asVoid()
this will discard any response body including any error response body. We should instead useasVoid()
if we might get an error response body that we want to read via for exampleHttpException.bean(Class)
.client.request() .path("hello/world") .GET() .async().asDiscarding() .whenComplete((hres, throwable) -> { if (throwable != null) { ... } else { int statusCode = hres.statusCode(); ... } });
- Returns:
- The CompletableFuture of the response
-
asString
CompletableFuture<HttpResponse<String>> asString()Process as String response body HttpResponse<String>.client.request() .path("hello/world") .GET() .async().asString() .whenComplete((hres, throwable) -> { if (throwable != null) { ... } else { int statusCode = hres.statusCode(); String body = hres.body(); ... } });
- Returns:
- The CompletableFuture of the response
-
asByteArray
CompletableFuture<HttpResponse<byte[]>> asByteArray()Process as response HttpResponse<byte[]>.- Returns:
- The CompletableFuture of the response
-
asLines
CompletableFuture<HttpResponse<Stream<String>>> asLines()Process as response HttpResponse<Stream<String>>.- Returns:
- The CompletableFuture of the response
-
asInputStream
CompletableFuture<HttpResponse<InputStream>> asInputStream()Process as response HttpResponse<InputStream>.- Returns:
- The CompletableFuture of the response
-
handler
Process with any givenHttpResponse.BodyHandler
.Example: line subscriber
Subscribe line by line to the response.
CompletableFuture<HttpResponse<Void>> future = client.request() .path("hello/lineStream") .GET().async() .handler(HttpResponse.BodyHandlers.fromLineSubscriber(new Flow.Subscriber<>() { @Override public void onSubscribe(Flow.Subscription subscription) { subscription.request(Long.MAX_VALUE); } @Override public void onNext(String item) { ... } @Override public void onError(Throwable throwable) { ... } @Override public void onComplete() { ... } })) .whenComplete((hres, throwable) -> { int statusCode = hres.statusCode(); ... });
- Parameters:
bodyHandler
- The body handler to use to process the response- Returns:
- The CompletableFuture of the response
-
as
Process converting the response body to the given type.If the HTTP statusCode is not in the 2XX range a HttpException is throw which contains the HttpResponse. This is the cause in the CompletionException.
client.request() ... .POST().async() .as(HelloDto.class) .whenComplete((helloResponse, throwable) -> { if (throwable != null) { HttpException httpException = (HttpException) throwable.getCause(); int statusCode = httpException.statusCode(); // maybe convert json error response body to a bean (using Jackson/Gson) MyErrorBean errorResponse = httpException.bean(MyErrorBean.class); .. } else { int statusCode = helloResponse.statusCode(); HelloDto helloDto = helloResponse.body(); ... } });
- Parameters:
type
- The bean type to convert the content to- Returns:
- The CompletableFuture of the response
-
as
The same asas(Class)
but using a generic type. -
bean
Process expecting a bean response body (typically from json content).If the HTTP statusCode is not in the 2XX range a HttpException is throw which contains the HttpResponse. This is the cause in the CompletionException.
client.request() ... .POST().async() .bean(HelloDto.class) .whenComplete((helloDto, throwable) -> { if (throwable != null) { HttpException httpException = (HttpException) throwable.getCause(); int statusCode = httpException.statusCode(); // maybe convert json error response body to a bean (using Jackson/Gson) MyErrorBean errorResponse = httpException.bean(MyErrorBean.class); .. } else { // process helloDto ... } });
- Parameters:
type
- The bean type to convert the content to- Returns:
- The CompletableFuture of the response
-
asList
Process converting the response body to a list of the given type.If the HTTP statusCode is not in the 2XX range a HttpException is throw which contains the HttpResponse. This is the cause in the CompletionException.
client.request() ... .POST().async() .asList(HelloDto.class) .whenComplete((helloResponse, throwable) -> { if (throwable != null) { // error response HttpException httpException = (HttpException) throwable.getCause(); int statusCode = httpException.statusCode(); // maybe convert json error response body to a bean (using Jackson/Gson) MyErrorBean errorResponse = httpException.bean(MyErrorBean.class); .. } else { // success response int statusCode = helloResponse.statusCode(); List<HelloDto> body = helloResponse.body(); ... } });
- Parameters:
type
- The type to convert the content to- Returns:
- The CompletableFuture of the response
-
asList
The same asasList(Class)
but using a generic type. -
list
Process expecting a list of beans response body (typically from json content).If the HTTP statusCode is not in the 2XX range a HttpException is throw which contains the HttpResponse. This is the cause in the CompletionException.
client.request() ... .GET().async() .list(HelloDto.class) .whenComplete((helloDtos, throwable) -> { if (throwable != null) { HttpException httpException = (HttpException) throwable.getCause(); int statusCode = httpException.statusCode(); ... } else { // process list of helloDto ... } });
- Parameters:
type
- The bean type to convert the content to- Returns:
- The CompletableFuture of the response
-
asStream
Process converting the response body to a stream of the given type.If the HTTP statusCode is not in the 2XX range a HttpException is throw which contains the HttpResponse. This is the cause in the CompletionException.
client.request() ... .POST().async() .asStream(HelloDto.class) .whenComplete((helloResponse, throwable) -> { if (throwable != null) { // error response HttpException httpException = (HttpException) throwable.getCause(); int statusCode = httpException.statusCode(); // maybe convert json error response body to a bean (using Jackson/Gson) MyErrorBean errorResponse = httpException.bean(MyErrorBean.class); .. } else { // success response int statusCode = helloResponse.statusCode(); Stream<HelloDto> body = helloResponse.body(); ... } });
- Parameters:
type
- The type to convert the content to- Returns:
- The CompletableFuture of the response
-
asStream
The same asasStream(Class)
but using a generic type. -
stream
Process response as a stream of beans (x-json-stream).Typically the response is expected to be application/x-json-stream newline delimited json payload.
Note that for this stream request the response content is not deemed 'loggable' by avaje-http-client. This is because the entire response may not be available at the time of the callback. As such
RequestLogger
will not include response content in logging stream request/response.If the HTTP statusCode is not in the 2XX range a HttpException is throw which contains the HttpResponse. This is the cause in the CompletionException.
CompletableFuture<Stream<Customer>> future = clientContext.request() .path("customers/stream") .GET().async() .stream(Customer.class); future.whenComplete((stream, throwable) -> { // if throwable != null ... handle error // else process Stream<Customer> ... try (stream) { stream.forEach(customer -> { ... }); } });
- Parameters:
type
- The bean type to convert the content to- Returns:
- The CompletableFuture of the response
-
bean
Process expecting a bean response body (typically from json content).- Parameters:
type
- The type to convert the content to- Returns:
- The CompletableFuture of the response
-
list
Process expecting a list of beans response body (typically from json content).- Parameters:
type
- The type to convert the content to- Returns:
- The CompletableFuture of the response
-
stream
Process response as a stream of beans (x-json-stream).- Parameters:
type
- The type to convert the content to- Returns:
- The CompletableFuture of the response
-