use of org.glassfish.jersey.client.spi.AsyncConnectorCallback in project jersey by jersey.
the class NettyConnector method apply.
@Override
public ClientResponse apply(ClientRequest jerseyRequest) {
final AtomicReference<ClientResponse> syncResponse = new AtomicReference<>(null);
final AtomicReference<Throwable> syncException = new AtomicReference<>(null);
try {
Future<?> resultFuture = apply(jerseyRequest, new AsyncConnectorCallback() {
@Override
public void response(ClientResponse response) {
syncResponse.set(response);
}
@Override
public void failure(Throwable failure) {
syncException.set(failure);
}
});
Integer timeout = ClientProperties.getValue(jerseyRequest.getConfiguration().getProperties(), ClientProperties.READ_TIMEOUT, 0);
if (timeout != null && timeout > 0) {
resultFuture.get(timeout, TimeUnit.MILLISECONDS);
} else {
resultFuture.get();
}
} catch (ExecutionException ex) {
Throwable e = ex.getCause() == null ? ex : ex.getCause();
throw new ProcessingException(e.getMessage(), e);
} catch (Exception ex) {
throw new ProcessingException(ex.getMessage(), ex);
}
Throwable throwable = syncException.get();
if (throwable == null) {
return syncResponse.get();
} else {
throw new RuntimeException(throwable);
}
}
use of org.glassfish.jersey.client.spi.AsyncConnectorCallback in project jersey by jersey.
the class JdkConnector method apply.
@Override
public Future<?> apply(final ClientRequest request, final AsyncConnectorCallback callback) {
final CompletableFuture<ClientResponse> responseFuture = new CompletableFuture<>();
// just so we don't have to drag around both the future and callback
final AsyncConnectorCallback internalCallback = new AsyncConnectorCallback() {
@Override
public void response(ClientResponse response) {
callback.response(response);
responseFuture.complete(response);
}
@Override
public void failure(Throwable failure) {
callback.failure(failure);
responseFuture.completeExceptionally(failure);
}
};
final HttpRequest httpRequest = createHttpRequest(request);
if (httpRequest.getBodyMode() == HttpRequest.BodyMode.BUFFERED) {
writeBufferedEntity(request, httpRequest, internalCallback);
}
if (httpRequest.getBodyMode() == HttpRequest.BodyMode.BUFFERED || httpRequest.getBodyMode() == HttpRequest.BodyMode.NONE) {
send(request, httpRequest, internalCallback);
}
if (httpRequest.getBodyMode() == HttpRequest.BodyMode.CHUNKED) {
/* We wait with sending the request header until the body stream has been touched.
This is because of javax.ws.rs.ext.MessageBodyWriter, which says:
"The message header map is mutable but any changes must be made before writing to the output stream since
the headers will be flushed prior to writing the message body"
This means that the headers can change until body output stream is used.
*/
final InterceptingOutputStream bodyStream = new InterceptingOutputStream(httpRequest.getBodyStream(), // send the prepared request when the stream is touched for the first time
() -> send(request, httpRequest, internalCallback));
request.setStreamProvider(contentLength -> bodyStream);
try {
request.writeEntity();
} catch (IOException e) {
internalCallback.failure(e);
}
}
return responseFuture;
}
Aggregations