Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle asynchronous callbacks in a synchronous way in Java?

I have an architechture related question. This is a language independent question, but as I come from Java background, it will be easier for me if someone guides me in the Java way.

Basically, the middleware I'm writing communicates with a SOAP based third party service. The calls are async - in a way that, when a service is called, it returns with a response 01 - processing; meaning that the third party has successfully received the request. In the original SOAP request, one callback URL has to be submitted each time, where third party actually sends the result. So, calling a particular service doesn't actually return the result immediately; the result is received in a separate HTTP endpoint in the middleware.

Now in our frontend, we don't want to complicate the user experience. We want our users to call a middleware function (via menu items/buttons), and get the result immediately; and leave the dirty work to the middleware.

Please note that the middleware function (lets say X()) which was invoked from the front end and the middleware endpoint URL(lets call it Y) where third party pushes the result are completely separate from each other. X() somehow has to wait and then fetch the result grabbed in Y and then return the result to the frontend.

enter image description here

How can I build a robust solution to achieve the above mentioned behavior? The picture depicts my case perfectly. Any suggestions will be highly appreciated.

like image 973
Tahniat Ashraf Avatar asked May 08 '18 06:05

Tahniat Ashraf


People also ask

Can callbacks be synchronous?

The callback is a function that's accepted as an argument and executed by another function (the higher-order function). There are 2 kinds of callback functions: synchronous and asynchronous. The synchronous callbacks are executed at the same time as the higher-order function that uses the callback.

What is asynchronous callback in Java?

Asynchronous CallbackAn Asynchronous call does not block the program from the code execution. When the call returns from the event, the call returns back to the callback function. So in the context of Java, we have to Create a new thread and invoke the callback method inside that thread.

What is synchronous and asynchronous calls in Java?

Synchronous means that you call a web service (or function or whatever) and wait until it returns - all other code execution and user interaction is stopped until the call returns. Asynchronous means that you do not halt all other operations while waiting for the web service call to return.

How do you make a method asynchronous in Java?

Since Java 5, the Future interface provides a way to perform asynchronous operations using the FutureTask. We can use the submit method of the ExecutorService to perform the task asynchronously and return the instance of the FutureTask. So let's find the factorial of a number: ExecutorService threadpool = Executors.


1 Answers

This question could be more about integration patterns than it is about multi-threading. But requests in the same application/JVM can be orchestrated using a combination of asynchronous invocation and the observer pattern:

This is better done using an example (exploiting your Java knowledge). Check the following simplistic components that try to replicate your scenario:

The third-party service: it exposes an operation that returns a correlation ID and starts the long-running execution

class ExternalService {
    public String send() {
        return UUID.randomUUID().toString();
    }
}

Your client-facing service: It receives a request, calls the third-party service and then waits for the response after registering with the result receiver:

class RequestProcessor {
    public Object submitRequest() {
        String correlationId = new ExternalService().send();

        return new ResultReceiver().register(correlationId).join();
    }
}

The result receiver: It exposes an operation to the third-party service, and maintains an internal correlation registry:

class ResultReceiver {

    Map<String, CompletableFuture<Object>> subscribers;

    CompletableFuture<Object> register(String responseId) {
        CompletableFuture<Object> future = new CompletableFuture<Object>();
        this.subscribers.put(responseId, future);

        return future;
    }

    public void externalResponse(String responseId, Object result) {
        this.subscribers.get(responseId).complete(result);
    }
}

Futures, promises, call-backs are handy in this case. Synchronization is done by the initial request processor in order to force the execution to block for the client.

Now this can raise a number of issues that are not addressed in this simplistic class set. Some of these problems may be:

  • race condition between new ExternalService().send() and new ResultReceiver().register(correlationId). This is something that can be solved in ResultReceiver if it undestands that some responses can be very fast (2-way wait, so to say)
  • Never-coming results: results can take too long or simply run into errors. These future APIs typically offer timeouts to force cancellation of the request. For example:

    new ResultReceiver().register(correlationId)
        .get(10000, TimeUnit.SECONDS);
    
like image 121
ernest_k Avatar answered Oct 03 '22 23:10

ernest_k