Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apply timeout control around Java operation

Tags:

java

timeout

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();
}
like image 744
Jon Cram Avatar asked Feb 12 '11 13:02

Jon Cram


People also ask

How do you implement timeout in Java?

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.

How do you handle timeout exception in Java?

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.

How do you implement timeout in REST API?

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.


2 Answers

I recommend TimeLimiter from Google Guava library.

like image 115
mindas Avatar answered Nov 15 '22 23:11

mindas


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();
    }
}
like image 45
user3151902 Avatar answered Nov 16 '22 00:11

user3151902