Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unirest shutdown to exit program

Tags:

java

unirest

I try to update resources with scheduled tasks using Unirest.get(...).asObjectAsync(...). To stop a program employing Unirest, you need to call Unirest.shutdown(); to exit its event loops and clients. However, if some threads call Unirest's request methods after a successful shutdown, the program can not exit.

The following code is a very simple example: I start a thread which does a GET request after 1.5 seconds and prints the status message when it was successful. Meanwhile on the main thread, Unirest is shut down. (Note that example this uses asStringAsync(...) and a very simple thread for simplicity.)

import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.async.Callback;
import com.mashape.unirest.http.exceptions.UnirestException;

import java.io.IOException;

public class Main {
    public static void main(String... args) throws IOException, InterruptedException {
        new Thread(() -> {
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Unirest.get("http://example.org").asStringAsync(new Callback<String>() {
                @Override
                public void completed(HttpResponse<String> response) {
                    System.out.println(response.getStatusText());
                }

                @Override
                public void failed(UnirestException e) {
                    System.out.println("failed");
                }

                @Override
                public void cancelled() {
                    System.out.println("cancelled");
                }
            });
        }).start();
        Unirest.shutdown();
    }
}

What I expected was any of these cases:

  • The program shuts down and no output is there.
  • The program shuts down and I get any of these outputs: the status message, failed or cancelled.
  • The program shuts down but throws an exception because Unirest is already shut when the GET request occurs.

What I got:

  • The program does not shut down and the GET request succeeds, printing "OK".

How can I handle a graceful exit with Unirest? Should I restructure the program (and if so, how)?

I am using Java 8 on Windows, running the code inside IntelliJ Idea 14.1.5. The unirest dependency I use is:

<dependency>
    <groupId>com.mashape.unirest</groupId>
    <artifactId>unirest-java</artifactId>
    <version>1.4.7</version>
</dependency>
like image 385
Sebastian Höffner Avatar asked Dec 11 '25 12:12

Sebastian Höffner


1 Answers

In your case, you have spawned a thread which runs the async call. The shutdown() call is in your main thread, so by the time that the call thread spawns, shutdown() will have been called before the asStringAsync() method of Unirest can be first called.

It is the first call to an ..Async() that instantiates the thread pool that will eventually need to be shut down - there is nothing to shut down at the time which you call the shutdown method, and so it is a no-op. It will be instantiated in the thread you created.

The solution here is to remove the thread that you have created, and make use the Future object that Unirest gives you. Unirest handles the thread itself when you do the async call, and you can input the callback logic as necessary.

    public static void main(String... args) throws IOException, InterruptedException, ExecutionException {
    Future<HttpResponse<String>> asyncCall = Unirest.get("http://thecatapi.com/api/images/get?format=xml&results_per_page=20").asStringAsync(new Callback<String>() {
        @Override
        public void completed(HttpResponse<String> response) {
            System.out.println(response.getStatusText());
        }

        @Override
        public void failed(UnirestException e) {
            System.out.println("failed");
        }

        @Override
        public void cancelled() {
            System.out.println("cancelled");
        }
    });
    HttpResponse<String> httpResponse = asyncCall.get(); // Can also use Future.isDone(), etc
    // System.out.println(httpResponse.getBody());
    Unirest.shutdown();
}
like image 170
Chris Riddell Avatar answered Dec 14 '25 03:12

Chris Riddell