adam bien's blog

Java 9 orTimeout and JAX-RS AsyncResponse 📎

Java 9 introduced the CompletableFuture#orTimeout method which allows the configuration of a "per pipeline" timeout. In case there are multpiple pipelines involved to answer a single request, the JAX-RS AsyncResponse#setTimeout method can be used to set the max duration (see it in action: javaeemicro.services) for the entire request:

import java.util.concurrent.CompletableFuture;
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) {

        CompletableFuture.supplyAsync(this::answer).
                thenAccept(response::resume).
                orTimeout(100, TimeUnit.MILLISECONDS).
                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 [...]/ping outputs:


HTTP/1.1 503 Service Unavailable
X-Powered-By: Servlet/4.0
cause: timeout in the pipeline
exception: java.util.concurrent.TimeoutException
Date: Fri, 01 Dec 2017 06:25:32 GMT
Content-Length: 0
Content-Language: en-DE
Connection: Close

See you at Java EE 8 on Java 9, at Munich Airport, Terminal 2