0

I have below DSS http connection to url:

private static HttpURLConnection connection(String urlSpec) {
        HttpURLConnection connection = new URL(urlSpec).openConnection() as HttpURLConnection
        connection.setRequestProperty('Prefer', 'respond-async, wait=60')
        connection.setRequestProperty('Accept', 'application/json')
 
        connection.setRequestMethod("POST")
        connection.setRequestProperty("Content-Type", "application/json; utf-8")
        connection.setDoOutput(true)
        connection
    }

Below is the part of my code where i am checking the http response and if the response is http 200 which is HTTP_OK then i can fetch the data and insert into database table. But now the problem is now during processing i am getting now in between Got http error code as 202 which is HTTP_ACCEPTED and for this reason i am not able to process this data into database table.

I think HTTP 202 is to be expected when requesting async. It means that server has received your query and is working on it. We need to keep checking the status of the request, by retrying the new URL sent in the 202 response, until you get HTTP 200. But i dont know how can i do this ?

Symonds
  • 184
  • 1
  • 2
  • 15

1 Answers1

1

Well, yes, you need to keep asking the remote resource if the task has been completed or not.

202 is non-committal, meaning that there is no way for the HTTP to later send an asynchronous response indicating the outcome of processing the request.

I see you're also working with "bare metal" utilities, such as HttpURLConnection, and that leads me to believe you do not have any library support for retrying HTTP calls.

In this case what you could do is spawn a new thread, maybe using an ExecutorService, and submit/execute a task which simply loops, e.g.

while (!Thread.interrupted()) { ... }

calling your URL until an HTTP_OK is received.


A skeleton could be

executorService.execute(() -> {
  while (!Thread.interrupted()) {
    // Return a valid value if `HTTP_OK`, otherwise `null`
    final var result = callRemoteUrl(url);
    
    if (result != null) {
      callback.call(result);
      return;
    }
  }
});

Where callback is an instance which receive the HTTP result asynchronously.


while (true)
  HttpURLConnection connection = connection("XXX.com")
  
  if (connection.responseCode >= HTTP_SERVER_ERROR) {
    // Server/internal error, we can't do anything
    // Maybe throw a custom Exception.
    break;
  }

  if (connection.responseCode != HTTP_OK) {
    try {
      // Adjust the delay between calls, in ms
      Thread.sleep(1000);
    } catch (final InterruptedException e) {
      // Ignore
    }
    
    // Try again
    continue;
  }
  
  println("Got http response code: ${connection.responseCode}, message: ${connection.responseMessage}")

  log.info("Successful request to ${connection.getURL()}")
  //println(connection.getInputStream().getText())

  LazyMap json = jsonFromExtractionConnection(connection)
  //Process the data from the response JSON and put it in the Map object for processing
  tryToProcessMarketDataFromExtractionJson(json, ricMap)

  // Filter the empty records out and take valid map from Data for inserting into DB table .
  def validMap = ricMap.findAll { key, val ->
      val.fs != null
  }

  insertIntoDb(validMap)
  writeToFile(outFile, sql(ORACLE), Select.query, Arrays.asList(Data.COLUMNS))
  
  // We're done, end the loop
  break;
}
LppEdd
  • 20,274
  • 11
  • 84
  • 139
  • i am quiet new with handling http request, response and rest api and also not used threading...could you please help me where actually i have to use this while loop and how ? and dont i need to handle http:202 separately like i did for http:200 ? will it work only with the thread ? – Symonds Feb 03 '21 at 16:20
  • what if i increase the wait time 'Prefer', 'respond-async, wait=60' ? – Symonds Feb 03 '21 at 16:22
  • @Symonds well your question is fairly broad, but you can check the edit I made for a starting point. – LppEdd Feb 03 '21 at 16:27
  • @Symonds the respond-async is just an header to influence the server behavior. – LppEdd Feb 03 '21 at 16:28
  • @Symonds I suggested to spawn a new thread to avoid blocking the entire application while it continues calling the URL. – LppEdd Feb 03 '21 at 16:31
  • i have just edited question and added one line for connection now HttpURLConnection connection = connection("XXX.com") I am bit confused now where actually we need to use executorService ? With this thread dont i need to check separately http:202 ? Will be really helpful if you can please suggest in my code where i have to make change for executorService...i would definately like to give try with this approach ..thanks – Symonds Feb 03 '21 at 16:35
  • @Symonds the `ExecutorService` call should be placed in another `if` branch for `HTTP_ACCEPTED`, e.g. `if (connection.responseCode == HTTP_ACCEPTED) { /* Spawn thread with callback */ }` – LppEdd Feb 03 '21 at 16:42
  • else if (connection.responseCode == HTTP_ACCEPTED) { executorService.execute(() -> { while (!Thread.interrupted()) { // Return a valid value if `HTTP_OK`, otherwise `null` final var result = callRemoteUrl(connection); if (result != null) { callback.call(result); return; } } }); } – Symonds Feb 03 '21 at 16:50
  • i have tried but getting error now ...executorService, callRemoteUrl, callback variable shoule be of which datatype ? And how this thread fits in my code which i mentioned in the question ? – Symonds Feb 03 '21 at 16:52
  • @Symonds that was just a skeleton. I suggest to study how threading works in Java before attempting this. Otherwise I'd have to rewrite all of your code – LppEdd Feb 03 '21 at 17:01
  • actually i will definately check about threading :) But does it require to rewrite everything ...i thought may be only the part where we have to handle HTTP:202 is sufficient ? – Symonds Feb 03 '21 at 17:11
  • Can we not use looping here simply i found one example but dont know how i can use this logic in my code ? while (respStatusCode == 202) { wait(30); responseGet = httpclient.execute(requestGet); respStatusCode = responseGet.getStatusLine().getStatusCode(); System.out.println("\nHTTP status: " + respStatusCode); } – Symonds Feb 03 '21 at 17:13
  • @Symonds looping is always necessary, it's the same thing I did with `while (!Thread.interrupted())` basically, the only difference is that in your example the condition is based on the HTTP code, and the loop is not in a separate thread, thus becoming *blocking*. – LppEdd Feb 03 '21 at 17:17
  • @Symonds see also this pseudocode for a solution without threading https://pastebin.com/KUzgLDGy – LppEdd Feb 03 '21 at 17:21
  • thanks ...is it possible for you to please just show the changes in my code about your logic --- i know i am asking too much may be but it will really helpful... – Symonds Feb 03 '21 at 17:21
  • how about i tried simply to use loop while (connection.responseCode == HTTP_ACCEPTED) { wait(30) ; if (connection.responseCode == HTTP_OK) { --remaining code – Symonds Feb 03 '21 at 17:29
  • @Symonds if the URL to contact is always the same it might be a viable road. Unfortunately only you know how all your project works, so it's up to you – LppEdd Feb 03 '21 at 17:35
  • @Symonds see my last edit for a rough idea. – LppEdd Feb 03 '21 at 17:45
  • thanks i will give try now :) i think HTTP_SERVER_ERROR is depriciated i am getting crossed line for this :) – Symonds Feb 03 '21 at 18:04
  • I have tried it works but somewhat i dont know it just hanged, i am waiting for more than 30 minutes its still hanged and not proceeding further requests :( – Symonds Feb 03 '21 at 19:34
  • @Symonds might be because the connection is stuck at waiting for a response, or is in a endless loop. Try to debug. – LppEdd Feb 03 '21 at 19:39
  • what does it mean endless loop in our case ? INormally the connection could never get stuck for 1 hour. – Symonds Feb 03 '21 at 19:58
  • @Symonds it means it keeps calling the URL and never exit the loop. But again you'd need to debug. – LppEdd Feb 03 '21 at 20:05