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:
What I got:
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>
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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With