diff --git a/azure-client-runtime/src/main/java/com/microsoft/azure/AzureClient.java b/azure-client-runtime/src/main/java/com/microsoft/azure/AzureClient.java index 62a760acb4a0d..39108162d2858 100644 --- a/azure-client-runtime/src/main/java/com/microsoft/azure/AzureClient.java +++ b/azure-client-runtime/src/main/java/com/microsoft/azure/AzureClient.java @@ -156,7 +156,7 @@ public ServiceResponseWithHeaders getPutOrPatchResultWi * @param callback the user callback to call when operation terminates. * @return the task describing the asynchronous polling. */ - public AsyncPollingTask getPutOrPatchResultAsync(Response response, Type resourceType, ServiceCall serviceCall, ServiceCallback callback) { + public AsyncPollingTask getPutOrPatchResultAsync(Response response, Type resourceType, ServiceCall serviceCall, ServiceCallback callback) { if (response == null) { callback.failure(new ServiceException("response is null.")); return null; @@ -211,7 +211,7 @@ public AsyncPollingTask getPutOrPatchResultAsync(Response r * @param callback the user callback to call when operation terminates. * @return the task describing the asynchronous polling. */ - public AsyncPollingTask getPutOrPatchResultWithHeadersAsync(Response response, Type resourceType, final Class headerType, final ServiceCall serviceCall, final ServiceCallback callback) { + public AsyncPollingTask getPutOrPatchResultWithHeadersAsync(Response response, Type resourceType, final Class headerType, final ServiceCall serviceCall, final ServiceCallback callback) { return this.getPutOrPatchResultAsync(response, resourceType, serviceCall, new ServiceCallback() { @Override public void failure(Throwable t) { @@ -329,7 +329,7 @@ public ServiceResponseWithHeaders getPostOrDeleteResult * @param callback the user callback to call when operation terminates. * @return the task describing the asynchronous polling. */ - public AsyncPollingTask getPostOrDeleteResultAsync(Response response, Type resourceType, ServiceCall serviceCall, ServiceCallback callback) { + public AsyncPollingTask getPostOrDeleteResultAsync(Response response, Type resourceType, ServiceCall serviceCall, ServiceCallback callback) { if (response == null) { callback.failure(new ServiceException("response is null.")); return null; @@ -383,7 +383,7 @@ public AsyncPollingTask getPostOrDeleteResultAsync(Response * @param callback the user callback to call when operation terminates. * @return the task describing the asynchronous polling. */ - public AsyncPollingTask getPostOrDeleteResultWithHeadersAsync(Response response, Type resourceType, final Class headerType, final ServiceCall serviceCall, final ServiceCallback callback) { + public AsyncPollingTask getPostOrDeleteResultWithHeadersAsync(Response response, Type resourceType, final Class headerType, final ServiceCall serviceCall, final ServiceCallback callback) { return this.getPostOrDeleteResultAsync(response, resourceType, serviceCall, new ServiceCallback() { @Override public void failure(Throwable t) { @@ -689,7 +689,7 @@ private Call pollAsync(String url, final ServiceCallback call = service.get(endpoint.getFile(), serviceClientUserAgent); - call.enqueue(new ServiceResponseCallback(callback) { + call.enqueue(new ServiceResponseCallback(null, callback) { @Override public void onResponse(Call call, Response response) { try { @@ -750,7 +750,7 @@ private interface AsyncService { */ abstract class AsyncPollingTask implements Runnable { /** The {@link Call} object from Retrofit. */ - protected ServiceCall serviceCall; + protected ServiceCall serviceCall; /** The polling state for the current operation. */ protected PollingState pollingState; /** The callback used for asynchronous polling. */ @@ -776,7 +776,7 @@ class PutPatchPollingTask extends AsyncPollingTask { * @param serviceCall the ServiceCall object tracking Retrofit calls. * @param clientCallback the client callback to call when a terminal status is hit. */ - PutPatchPollingTask(final PollingState pollingState, final String url, final ServiceCall serviceCall, final ServiceCallback clientCallback) { + PutPatchPollingTask(final PollingState pollingState, final String url, final ServiceCall serviceCall, final ServiceCallback clientCallback) { this.serviceCall = serviceCall; this.pollingState = pollingState; this.url = url; @@ -833,7 +833,7 @@ class PostDeletePollingTask extends AsyncPollingTask { * @param serviceCall the ServiceCall object tracking Retrofit calls. * @param clientCallback the client callback to call when a terminal status is hit. */ - PostDeletePollingTask(final PollingState pollingState, final ServiceCall serviceCall, final ServiceCallback clientCallback) { + PostDeletePollingTask(final PollingState pollingState, final ServiceCall serviceCall, final ServiceCallback clientCallback) { this.serviceCall = serviceCall; this.pollingState = pollingState; this.clientCallback = clientCallback; @@ -861,14 +861,20 @@ public void run() { && !pollingState.getLocationHeaderLink().isEmpty()) { updateStateFromLocationHeaderOnPostOrDeleteAsync(pollingState, pollingCallback); } else { - pollingCallback.failure(new ServiceException("No header in response")); + ServiceException serviceException = new ServiceException("No async header in response"); + pollingCallback.failure(serviceException); + serviceCall.failure(serviceException); } } else { // Check if operation failed if (AzureAsyncOperation.getFailedStatuses().contains(pollingState.getStatus())) { - clientCallback.failure(new ServiceException("Async operation failed")); + ServiceException serviceException = new ServiceException("Async operation failed"); + clientCallback.failure(serviceException); + serviceCall.failure(serviceException); } else { - clientCallback.success(new ServiceResponse<>(pollingState.getResource(), pollingState.getResponse())); + ServiceResponse serviceResponse = new ServiceResponse<>(pollingState.getResource(), pollingState.getResponse()); + clientCallback.success(serviceResponse); + serviceCall.success(serviceResponse); } } } diff --git a/client-runtime/src/main/java/com/microsoft/rest/ServiceCall.java b/client-runtime/src/main/java/com/microsoft/rest/ServiceCall.java index dcffd781c7c59..94b1abfb9bb63 100644 --- a/client-runtime/src/main/java/com/microsoft/rest/ServiceCall.java +++ b/client-runtime/src/main/java/com/microsoft/rest/ServiceCall.java @@ -7,14 +7,18 @@ package com.microsoft.rest; +import com.google.common.util.concurrent.AbstractFuture; + import retrofit2.Call; /** * An instance of this class provides access to the underlying REST call invocation. * This class wraps around the Retrofit Call object and allows updates to it in the * progress of a long running operation or a paging operation. + * + * @param the type of the returning object */ -public class ServiceCall { +public class ServiceCall extends AbstractFuture> { /** * The Retrofit method invocation. */ @@ -62,4 +66,26 @@ public void cancel() { public boolean isCanceled() { return call.isCanceled(); } + + /** + * Invoke this method to report completed, allowing + * {@link AbstractFuture#get()} to be unblocked. + * + * @param result the service response returned. + * @return true if successfully reported; false otherwise. + */ + public boolean success(ServiceResponse result) { + return set(result); + } + + /** + * Invoke this method to report a failure, allowing + * {@link AbstractFuture#get()} to throw the exception. + * + * @param t the exception thrown. + * @return true if successfully reported; false otherwise. + */ + public boolean failure(Throwable t) { + return setException(t); + } } diff --git a/client-runtime/src/main/java/com/microsoft/rest/ServiceResponseCallback.java b/client-runtime/src/main/java/com/microsoft/rest/ServiceResponseCallback.java index 8808bfac9639c..a808869960294 100644 --- a/client-runtime/src/main/java/com/microsoft/rest/ServiceResponseCallback.java +++ b/client-runtime/src/main/java/com/microsoft/rest/ServiceResponseCallback.java @@ -18,6 +18,11 @@ * @param the response body type */ public abstract class ServiceResponseCallback implements Callback { + /** + * The client service call object. + */ + private ServiceCall serviceCall; + /** * The client callback. */ @@ -26,14 +31,21 @@ public abstract class ServiceResponseCallback implements Callback serviceCallback) { + public ServiceResponseCallback(ServiceCall serviceCall, ServiceCallback serviceCallback) { + this.serviceCall = serviceCall; this.serviceCallback = serviceCallback; } @Override public void onFailure(Call call, Throwable t) { - serviceCallback.failure(new ServiceException(t)); + if (serviceCallback != null) { + serviceCallback.failure(t); + } + if (serviceCall != null) { + serviceCall.failure(t); + } } } diff --git a/client-runtime/src/main/java/com/microsoft/rest/ServiceResponseEmptyCallback.java b/client-runtime/src/main/java/com/microsoft/rest/ServiceResponseEmptyCallback.java index fe848128c57df..2a82667795b27 100644 --- a/client-runtime/src/main/java/com/microsoft/rest/ServiceResponseEmptyCallback.java +++ b/client-runtime/src/main/java/com/microsoft/rest/ServiceResponseEmptyCallback.java @@ -17,6 +17,11 @@ * @param the response body type */ public abstract class ServiceResponseEmptyCallback implements Callback { + /** + * The client service call object. + */ + private ServiceCall serviceCall; + /** * The client callback. */ @@ -25,14 +30,21 @@ public abstract class ServiceResponseEmptyCallback implements Callback /** * Creates an instance of ServiceResponseCallback. * + * @param serviceCall the client service call to call on a terminal state. * @param serviceCallback the client callback to call on a terminal state. */ - public ServiceResponseEmptyCallback(ServiceCallback serviceCallback) { + public ServiceResponseEmptyCallback(ServiceCall serviceCall, ServiceCallback serviceCallback) { + this.serviceCall = serviceCall; this.serviceCallback = serviceCallback; } @Override public void onFailure(Call call, Throwable t) { - serviceCallback.failure(new ServiceException(t)); + if (serviceCallback != null) { + serviceCallback.failure(t); + } + if (serviceCall != null) { + serviceCall.failure(t); + } } }