I'm using a third party Java library to interact with a REST API. The REST API can sometimes take a long time to respond, eventually resulting in a java.net.ConnectException
being thrown.
I'd like to shorten the timeout period but have no means of modifying the third party library.
I'd like to apply some form of timeout control around the calling of a Java method so that I can determine at what point to give up waiting.
This doesn't relate directly to network timeouts. I'd like to be able to try and perform an operation and be able to give up after a specified wait time.
The following is by no means valid Java but does conceptually demonstrate what I'd like to achieve:
try {
Entity entity = new Entity();
entity.methodThatMakesUseOfRestApi();
} catch (<it's been ages now, I don't want to wait any longer>) {
throw TimeoutException();
}
Using a Loop long start = System. currentTimeMillis(); long end = start + 30 * 1000; while (System. currentTimeMillis() < end) { // Some expensive operation on the item. } Here, the loop will break if the time has surpassed the limit of 30 seconds.
Blocking operations for which a timeout is specified need a means to indicate that the timeout has occurred. For many such operations it is possible to return a value that indicates timeout; when that is not possible or desirable then TimeoutException should be declared and thrown.
One way we can implement a request timeout on database calls is to take advantage of Spring's @Transactional annotation. It has a timeout property that we can set. The default value for this property is -1, which is equivalent to not having any timeout at all.
I recommend TimeLimiter from Google Guava library.
This is probably the current way how this should be done with plain Java:
public String getResult(final RESTService restService, String url) throws TimeoutException {
// should be a field, not a local variable
ExecutorService threadPool = Executors.newCachedThreadPool();
// Java 8:
Callable<String> callable = () -> restService.getResult(url);
// Java 7:
// Callable<String> callable = new Callable<String>() {
// @Override
// public String call() throws Exception {
// return restService.getResult(url);
// }
// };
Future<String> future = threadPool.submit(callable);
try {
// throws a TimeoutException after 1000 ms
return future.get(1000, TimeUnit.MILLISECONDS);
} catch (ExecutionException e) {
throw new RuntimeException(e.getCause());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new TimeoutException();
}
}
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