adam bien's blog

Pipeline-specific timeouts with CompletableFuture#orTimeout and JAX-RS 2.1 📎

CompletableFuture#orTimeout (>= Java 9) method

"...exceptionally completes this CompletableFuture with a TimeoutException if not otherwise completed before the given timeout. ..."
and is therefore well suited to set a pipeline-specific timeout.

The method AsyncResponse#setTimeout sets the max timeout per request:


import static java.util.concurrent.CompletableFuture.supplyAsync;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.container.Suspended;
import javax.ws.rs.core.Response;

@Path("ping")
public class PingResource {

    @GET
    public void ping(@Suspended AsyncResponse response) {
        response.setTimeout(1, TimeUnit.SECONDS); //global timeout
        supplyAsync(this::answer).
                thenAccept(response::resume).
                orTimeout(100, TimeUnit.MILLISECONDS). //pipeline specific timeout
                exceptionally((t) -> handleTimeout(response::resume, t));
    }

    Void handleTimeout(Consumer<Response> consumer, Throwable t) {
        consumer.accept(Response.status(503).
                header("cause", "timeout in the pipeline").
                header("exception", t.toString()).
                build());
        return null;
    }

    public String answer() {
        try {
            Thread.sleep(200);
            return "42 + " + System.currentTimeMillis();
        } catch (InterruptedException ex) {
            throw new IllegalStateException("cannot sleep");
        }
    }
}

The request: curl -i http://localhost:8080/completable-timeout/resources/ping returns:


HTTP/1.1 503 Service Unavailable
X-Powered-By: Servlet/4.0
cause: timeout in the pipeline
exception: java.util.concurrent.TimeoutException
(...)

See you at Java EE 8 / Java 9 / Web Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.