8000 feat: Add optional Virtual Thread support to JettyComponent (#88) by kawasima · Pull Request #90 · enkan/enkan · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.eclipse.jetty.util.thread.VirtualThreadPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -117,6 +118,9 @@ private ServerConnector createHttpConnector(Server server, OptionMap options) {
}

private ThreadPool createThreadPool(OptionMap options) {
if (options.getBoolean("virtualThreads?", false)) {
return new VirtualThreadPool();
}
QueuedThreadPool pool = new QueuedThreadPool(options.getInt("maxThreads", 50));
pool.setMinThreads(options.getInt("minThreads", 8));
return pool;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
public class JettyComponent extends WebServerComponent<JettyComponent> implements HealthCheckable {
private Server server;
private BiFunction<Server, OptionMap, Connector> serverConnectorFactory;
private boolean virtualThreads = true;
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The project requires Java 25 (set in the parent pom.xml as <java.version>25</java.version>), so Virtual Threads are always available and production-ready. Defaulting to true ensures users get VirtualThreadPool out of the box without explicit configuration. The PR description has been updated to reflect this intent.


@Override
protected ComponentLifecycle<JettyComponent> lifecycle() {
Expand All @@ -35,6 +36,7 @@ public void start(JettyComponent component) {
OptionMap options = buildOptionMap();
if (serverConnectorFactory != null) options.put("serverConnectorFactory", serverConnectorFactory);
options.put("join?", false);
options.put("virtualThreads?", virtualThreads);
if (!(app.getApplication() instanceof WebApplication webApp)) {
throw new MisconfigurationException("web.APPLICATION_NOT_WEB");
}
Expand Down Expand Up @@ -64,6 +66,14 @@ public HealthStatus health() {
return (server != null && server.isRunning()) ? HealthStatus.UP : HealthStatus.DOWN;
}

public boolean isVirtualThreads() {
return virtualThreads;
}

public void setVirtualThreads(boolean virtualThreads) {
this.virtualThreads = virtualThreads;
}

/**
* Set a factory of jetty connector.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;

import org.eclipse.jetty.util.thread.VirtualThreadPool;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -229,6 +231,43 @@ public <NNREQ, NNRES> HttpResponse handle(HttpRequest req,
.isEqualTo("mapped");
}

// ---------------------------------------------------- virtual threads

@Test
void virtualThreadPoolStartsAndHandlesRequest() throws Exception {
int vtPort;
try (ServerSocket s = new ServerSocket(0)) {
vtPort = s.getLocalPort();
}
WebApplication app = new WebApplication();
app.use(Predicates.any(), "vt", new WebMiddleware() {
@Override
public <NNREQ, NNRES> HttpResponse handle(HttpRequest req,
enkan.MiddlewareChain<HttpRequest, HttpResponse, NNREQ, NNRES> chain) {
HttpResponse res = HttpResponse.of("vt-ok");
res.setHeaders(Headers.empty());
return res;
}
});
OptionMap options = OptionMap.of("http?", true, "port", vtPort, "host", "127.0.0.1",
"join?", false, "virtualThreads?", true);
Server vtServer = new JettyAdapter().runJetty(app, options);
Comment on lines +252 to +254
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Added assertThat(vtServer.getThreadPool()).isInstanceOf(VirtualThreadPool.class) before the HTTP request, which directly verifies that the VirtualThreadPool is selected when virtualThreads? is true.

try {
assertThat(vtServer.getThreadPool()).isInstanceOf(VirtualThreadPool.class);

URI uri = URI.create("http://127.0.0.1:" + vtPort + "/");
HttpURLConnection conn = (HttpURLConnection) uri.toURL().openConnection();
conn.setConnectTimeout(3000);
conn.setReadTimeout(3000);
assertThat(conn.getResponseCode()).isEqualTo(200);
assertThat(new String(conn.getInputStream().readAllBytes(), StandardCharsets.UTF_8))
.isEqualTo("vt-ok");
} finally {
vtServer.stop();
vtServer.join();
}
}

// ----------------------------------------------------------- SSL config

@Test
Expand Down
0