I want to implement a timeout for a process, if it takes more than X amount of seconds, I want it to stop and execute the return statement regardless. In my real world use I would be calling a REST API, apiCallController() represents the Controller.
With what I've tried below everything just keeps on executing regardless.
How do I pull this off?
EDIT: If what I'm trying to achieve works, the long running task won't complete which means that the line
System.out.println("End http/SSH stuff...");
will never print, and this line
response = "Call successful...";
will not be executed either, leaving the response variable as originally initialized
String response = "Call aborted...";
But I still need to return the response after the timeout
I've been testing in this Java fiddle (you can just paste the code): https://javafiddle.leaningtech.com/
Thanks.
import java.util.*;
import java.lang.*;
public class JavaFiddle
{
public static void main(String[] args)
{
String response = apiCallController();
System.out.println(response);
}
public static String apiCallController() {
System.out.println("creepy...\n");
int timeoutSeconds = 2;
int longRunningTaskDurationSeconds = 5;
String response = "Call aborted...";
try
{
new Timer().schedule(
new TimerTask() {
@Override
public void run() {
System.out.println("Timeout reached, aborting... (This is where I want everything to stop without killing JVM/Tomcat)");
// System.exit(0); This guy shut tomcat down x_X
return;
}
},
timeoutSeconds * 1000
);
System.out.println("Start http/SSH stuff...");
Thread.sleep(longRunningTaskDurationSeconds * 1000);
System.out.println("End http/SSH stuff...");
response = "Call successful...";
}
catch(InterruptedException e)
{
System.out.println(e);
}
System.out.println("\npasta...");
return "\n" + response;
}
}
EDIT 2: From the accepted answer, I just refactored a touch:
import java.util.*;
import java.lang.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ExecutionException;
public class JavaFiddle
{
public static void main(String[] args)
{
System.out.println("creepy...\n\n");
String response = apiCallController();
System.out.println(response);
System.out.println("\n\npasta...");
}
public static String apiCallController() {
String response = "Stuff TIMED out...";
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
Callable<String> r = () -> {
try {
System.out.println("Start http/SSH stuff...");
TimeUnit.SECONDS.sleep(5);
System.out.println("End http/SSH stuff...");
return "Stuff COMPLETED successfully...";
} catch (InterruptedException e) {
throw e;
}
};
Future<String> task = executor.submit(r);
try {
response = task.get(3, TimeUnit.SECONDS);
} catch(InterruptedException | TimeoutException e) {
task.cancel(true);
} catch (ExecutionException e) {
e.printStackTrace();
}
// Need to shutdown executor (think of it is master thread here)
// You may want to control this behaviour outside of this function call
executor.shutdown();
return "\n" + response;
}
}
timeout*1000?timeoutSeconds * 1000with the more obviousDuration.ofSeconds( timeoutSeconds ).toMillis(). Even better, change the type oftimeoutSecondsto be aDurationobject namedtimeout.