diff --git a/avaje-jex/src/main/java/io/avaje/jex/DJexConfig.java b/avaje-jex/src/main/java/io/avaje/jex/DJexConfig.java index bdcd54b8..1d5473e0 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/DJexConfig.java +++ b/avaje-jex/src/main/java/io/avaje/jex/DJexConfig.java @@ -2,6 +2,8 @@ import java.util.HashMap; import java.util.Map; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; import java.util.function.Consumer; import com.sun.net.httpserver.HttpsConfigurator; @@ -19,6 +21,7 @@ final class DJexConfig implements JexConfig { private int socketBacklog = 0; private boolean health = true; private boolean ignoreTrailingSlashes = true; + private Executor executor; private JsonService jsonService; private final Map renderers = new HashMap<>(); private HttpsConfigurator httpsConfig; @@ -81,6 +84,22 @@ public JexConfig renderer(String extension, TemplateRender renderer) { return this; } + @Override + public Executor executor() { + if (executor == null) { + executor = + Executors.newThreadPerTaskExecutor( + Thread.ofVirtual().name("avaje-jex-http-", 0).factory()); + } + return executor; + } + + @Override + public JexConfig executor(Executor executor) { + this.executor = executor; + return this; + } + @Override public String host() { return host; diff --git a/avaje-jex/src/main/java/io/avaje/jex/JexConfig.java b/avaje-jex/src/main/java/io/avaje/jex/JexConfig.java index 9005fd39..6db7bf13 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/JexConfig.java +++ b/avaje-jex/src/main/java/io/avaje/jex/JexConfig.java @@ -1,6 +1,8 @@ package io.avaje.jex; import java.util.Map; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; import java.util.function.Consumer; import com.sun.net.httpserver.HttpServer; @@ -41,6 +43,19 @@ public interface JexConfig { */ JexConfig contextPath(String contextPath); + /** + * Executor for serving requests. Defaults to a {@link + * Executors#newVirtualThreadPerTaskExecutor()} + */ + Executor executor(); + + /** + * Sets the executor service used to handle incoming requests. + * + * @param executor The executor service. + */ + JexConfig executor(Executor executor); + /** Returns whether the health endpoint is enabled. */ boolean health(); diff --git a/avaje-jex/src/main/java/io/avaje/jex/core/BootstrapServer.java b/avaje-jex/src/main/java/io/avaje/jex/core/BootstrapServer.java index a82824ea..9348feba 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/core/BootstrapServer.java +++ b/avaje-jex/src/main/java/io/avaje/jex/core/BootstrapServer.java @@ -8,7 +8,6 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; -import java.util.concurrent.Executors; import com.sun.net.httpserver.HttpServer; @@ -62,9 +61,7 @@ static Jex.Server start(Jex jex, SpiRoutes routes) { // jetty's server does not support setExecutor with virtual threads (VT) // as it has it's own impl that will auto-use VTs if (!serverClass.getName().contains("jetty")) { - server.setExecutor( - Executors.newThreadPerTaskExecutor( - Thread.ofVirtual().name("avaje-jex-http-", 0).factory())); + server.setExecutor(config.executor()); } server.createContext(contextPath, handler); diff --git a/avaje-jex/src/main/java/io/avaje/jex/http/ExchangeHandler.java b/avaje-jex/src/main/java/io/avaje/jex/http/ExchangeHandler.java index 2b9ef63f..70577324 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/http/ExchangeHandler.java +++ b/avaje-jex/src/main/java/io/avaje/jex/http/ExchangeHandler.java @@ -1,5 +1,7 @@ package io.avaje.jex.http; +import java.io.IOException; + /** * A functional interface representing an HTTP request handler. * @@ -19,7 +21,7 @@ public interface ExchangeHandler { * parameters, and body, as well as methods for constructing and sending the response. * * @param ctx The context object containing the request and response details. - * @throws Exception if an error occurs during request processing or response generation. + * @throws IOException if an I/O error occurs during request processing or response generation. */ void handle(Context ctx) throws Exception; }