Currently, I have this JsonBodyHandler
used to parse the response body if the response is successful. I also have a model defined if the request is not successful. So based on the status code, I need to map the response to either the expected or exception model classes.
private static class JsonBodyHandler<R> implements HttpResponse.BodyHandler<Supplier<R>> {
private final Class<R> returnClz;
public JsonBodyHandler(Class<R> returnClz) {
this.returnClz = returnClz;
}
private static <R> HttpResponse.BodySubscriber<Supplier<R>> asJson(Class<R> returnClz) {
HttpResponse.BodySubscriber<InputStream> upstream =
HttpResponse.BodySubscribers.ofInputStream();
return HttpResponse.BodySubscribers.mapping(
upstream, inputStream -> toSupplierOfType(inputStream, returnClz));
}
private static <R> Supplier<R> toSupplierOfType(InputStream inputStream, Class<R> returnClz) {
return () -> {
try (InputStream stream = inputStream) {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(stream, returnClz);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
};
}
@Override
public HttpResponse.BodySubscriber<Supplier<R>> apply(HttpResponse.ResponseInfo responseInfo) {
return asJson(returnClz);
}
}
I'm sending requests as follows:
<B, R> R exchange(URI uri, String method, B body, Class<R> returnClz) {
Builder httpRequestBuilder = HttpRequest.newBuilder().uri(uri);
addHeaders(httpRequestBuilder);
var httpRequest =
"GET".equals(method)
? httpRequestBuilder.GET().build()
: httpRequestBuilder.method(method, getBodyPublisher(body)).build();
var httpClient = HttpClient.newHttpClient();
JsonBodyHandler<R> bodyHandler = new JsonBodyHandler<>(returnClz);
Supplier<R> responseSupplier = httpClient.send(httpRequest, bodyHandler).body();
return responseSupplier.get();
}
What I want to do is something as follows:
BodySubscriber<Supplier<R>> successBodySubscriber = JsonBodyHandler.asJson(returnClz);
BodySubscriber<Supplier<ExceptionModel>> failureBodySubscriber =
JsonBodyHandler.asJson(ExceptionModel.class);
BodyHandler<Supplier> jsonBodyHandler =
(rspInfo) -> rspInfo.statusCode() == 200 ? successBodySubscriber : failureBodySubscriber;
HttpResponse<Supplier> httpResponse = httpClient.send(httpRequest, jsonBodyHandler);
if (httpResponse.statusCode() != 200) {
Supplier<ExceptionModel> responseSupplier = httpResponse.body();
throw ClientServiceError.invalidResponse(responseSupplier.get());
}
Supplier<R> responseSupplier = httpResponse.body();
return responseSupplier.get();
This doesn't work, I get compile time error at line BodyHandler<Supplier> jsonBodyHandler = (rspInfo) -> rspInfo.statusCode() == 200 ? successBodySubscriber : failureBodySubscriber;
:
Incompatible types. Found: 'java.net.http.HttpResponse.BodySubscriber<java.util.function.Supplier>', required: 'java.net.http.HttpResponse.BodySubscriber<java.util.function.Supplier>'
Incompatible types. Found: 'java.net.http.HttpResponse.BodySubscriber<java.util.function.Supplier<com.project.proxy.impl.ExceptionModel>>', required: 'java.net.http.HttpResponse.BodySubscriber<java.util.function.Supplier>'
I am using Java 11. Cannot upgrade the version. I believe there should be a better way to do this. Any suggestions will be appreciated.