How to abstract asynchronous HTTP requests as synchronous

kosgeinsky :

I have a third party REST API service that behaves 'asynchronously'; as in requests respond with intermediate responses that are supplemented by callbacks with a correlator to the intermediate response.

The callbacks are returned almost immediately via a 'callback URL'.

I am trying to devise a solution, sort of an adapter to call this resource as though it was 'synchronous' because it is cumbersome to deal with the callbacks, especially when I need to batch successive requests serially to other similar APIs by the same thirdparty. Basically I want to abstract the green part so that the caller only gets full callback, an error or timeout exception. enter image description here

My research points at using RxJava but I can't figure out how this problem can be solved by principles of reactive programming(my understanding is limited).

Design considerations:

  1. Persisting correlator to a datastore for later lookup upon callback is not desirable because it is expensive
  2. Wait strategy for the callback is OK because the response times for the callback is less than 1 sec

How can I employ a CompletableFuture, or Observable-Observer pattern to wait for the callback and return to the caller?

starikoff :

If you have this:

public ImmediateResponse asynchCall(Callback callback) throws ImmediateException {...}

Where Callback looks like this:

interface Callback {
    void onSuccess(EventualResponse eventualResponse);
    void onFailure(Exception e);
}

Then what you want is something like this:

public static EventualResponse synchCall(long timeout, TimeUnit timeUnit)
        throws InterruptedException, TimeoutException, EventualException
{
    CompletableFuture<EventualResponse> responseFuture = new CompletableFuture<>();
    Callback callback = new Callback() {
        public void onSuccess(EventualResponse response) { 
            responseFuture.complete(response); 
        }
        public void onFailure(Exception e) { 
            responseFuture.completeExceptionally(e); 
        }
    };
    try {
        /*ImmediateResponse immediateResponse = */asynchCall(callback); 
        // use immediateResponse if you need it
        return responseFuture.get(timeout, timeUnit);
    } catch (ImmediateException e) {
        throw new EventualException(e);
    } catch (ExecutionException ee) {
        throw new EventualException(ee.getCause());
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=108553&siteId=1