1

I am calling a REST API synchronously from a Spring boot app (in JAVA 11) to download a file.

This is how the REST API looks like:

@GetMapping("/download/{userId}/{fileName}")
public String download(final int userId, final String fileName) {
        if(requested file is available) {
             return {file location URL}
        } else {
             Begin generating a new file (takes 5 seconds to more than 5 minutes)
             return "file generation in progress" 
        } 
    }

The API returns two things, either it returns the status of the file if it is generating the file (which takes anywhere from 5 seconds to 5 minutes or more), or the file location URL itself if the file is generated.

The problem I am trying to solve is, I need to call this "/download" API every 5 seconds and check if the file is ready or not.

Something like this:

  • First call the "/download" -> API returns "file generation in progress" status
  • so, call it again after 5 seconds -> API returns the "file generation in progress" status again
  • so, call it again after 5 seconds -> API returns the "file generation in progress" status again (But by this time assume that the file is generated)
  • so, call it another time after 5 seconds -> API returns the file location URL
  • Stop calling the API and do the next things

Is there a way I can achieve this? I tried looking CompletableFuture & @Scheduled but I am so new to both of these options and couldn't find any way to implement them in my code. Any help would be appreciated!

AMagic
  • 2,690
  • 3
  • 21
  • 33
  • Could you just call the API and check the how much is the download going, like percentage? check this : https://stackoverflow.com/questions/22273045/java-getting-download-progress – PatrickChen May 10 '20 at 05:43

1 Answers1

1

You can make use of the Java Failsafe Library. Refer the answer from [Retry a method based on result (instead of exception). I have modified the code from the answer to match your scenario.

private String downloadFileWithRetry() {
    final RetryPolicy<String> retryPolicy = new RetryPolicy<String>()
        .withMaxAttempts(-1)
        .handleResultIf("file generation in progress"::equalsIgnoreCase);

    return Failsafe
        .with(retryPolicy)
        .onSuccess(response -> System.out.println("Generated file Url is ".concat(response.getResult())))
        .get(this::downloadFile);
}

private String downloadFile() {
    return "file generation in progress";
}
  • Thanks, Ramachandran. I am trying your solution out and it does call the API on repeat, but if the API throws an exception, Failsafe doesn't break out of the loop. I am trying methods like Failsafe.abortIf() and Failsafe.abortWhen() but they aren't working for me. – AMagic May 12 '20 at 03:26
  • @AMagic make use of handleIf method like `.handleIf(it -> false)` – Ramachandran Murugaian May 12 '20 at 04:55