Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jetty-users] Building response for request that is sleeping

Hi,

On Thu, Jul 8, 2021 at 6:45 AM Aniruddha Tekade via jetty-users
<jetty-users@xxxxxxxxxxx> wrote:
>
> Hi All,
>
> I am trying to build a response for a request that is saved in hashmap. But I am not sure how can I solve this problem - should I use async mechanism or multithreading and how?
>
> Request A is sent to a doGET() method to be served but doGET makes some changes and makes another request B to the outside server.
> I save the request with its UUID request ID into a hashmap
> The outside server sends 200 OK back for new request B.
> The outside server then makes a POST request which has data to be sent back to request A.

If this last bullet is true, it's quite a complicated scenario (what
if the POST never arrives, what if the POST arrives before the 200 OK,
etc.).

AsyncMiddleManServlet won't help you because your stuff is not really
a proxy, but more like a hub so you have to write your own code.

> But I am super confused about how can I send this data with a response back to request A as a response?

You need to get familiar with asynchronous request processing
introduced in Servlet 3.0, search for tutorials on
ServletRequest.startAsync().
You also need an asynchronous HttpClient like Jetty's.

Then this pseudocode:

doGet(requestA) {
  AsyncContext ctxA = requestA.startAsync();
  CompletableFuture cf200 = new CompletableFuture();
  CompletableFuture cfPOST = new CompletableFuture();
  CompletableFuture cf = cf200.thenCombine(cfPOST, (ignored,
responseC) -> responseC)
    .thenAccept(responseC -> sendResponseA(ctxA, responseC.getStatus()));
  map.put(uniqueID, cfPOST);
  sendRequestB(responseB -> {
    int statusB = responseB.getStatus();
    if (statusB == 200) {
      cf200.complete(null);
    } else {
      map.remove(uniqueID);
      sendResponseA(ctxA, statusB);
    }
  });
}

doPost(requestC) {
  cfPOST = map.remove(requestID);
  cfPOST.complete(responseC);
}

sendResponseA(ctxA, int statusC) {
  ctxA.getResponse().setStatus(statusC);
  ctxA.complete();
}

The idea is to receive requestA, organize the hub with 2
CompletableFutures, send requestB and exit.
Then wait for cf200 and cfPOST to complete.
When both are completed, cf will be completed as well and will send
the response back to A.

Method sendRequestB(...) sends the request to B asynchronously.

The code above lacks timeouts (both request B and C can timeout),
error handling, etc. but it should give you a starting point.

-- 
Simone Bordet
----
http://cometd.org
http://webtide.com
Developer advice, training, services and support
from the Jetty & CometD experts.


Back to the top