From c701e387373fc624d9014d698e9e4a4384b25f39 Mon Sep 17 00:00:00 2001 From: Laird Nelson Date: Thu, 29 Oct 2020 10:52:39 -0700 Subject: [PATCH] Initial stab at incorporating some Loom features into Helidon in a way that will work under JDK 11 or 16-loom-ea (#2417) Signed-off-by: Laird Nelson --- .../server/ServerCdiExtension.java | 29 +++++++++++++-- pom.xml | 29 +++++++++++++++ .../jersey/AsyncExecutorProvider.java | 36 +++++++++++++++++-- 3 files changed, 89 insertions(+), 5 deletions(-) diff --git a/microprofile/server/src/main/java/io/helidon/microprofile/server/ServerCdiExtension.java b/microprofile/server/src/main/java/io/helidon/microprofile/server/ServerCdiExtension.java index 417c6764f..0ddc0fdbb 100644 --- a/microprofile/server/src/main/java/io/helidon/microprofile/server/ServerCdiExtension.java +++ b/microprofile/server/src/main/java/io/helidon/microprofile/server/ServerCdiExtension.java @@ -27,6 +27,7 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; @@ -108,10 +109,34 @@ public class ServerCdiExtension implements Extension { // make sure all configuration is in place if (null == jaxRsExecutorService) { - jaxRsExecutorService = ServerThreadPoolSupplier.builder() + Config serverConfig = config.get("server"); + final java.lang.reflect.Method m; + if (serverConfig.get("virtual-threads").asBoolean().orElse(false)) { + java.lang.reflect.Method temp = null; + try { + temp = Executors.class.getDeclaredMethod("newVirtualThreadExecutor"); + } catch (final ReflectiveOperationException notLoomEarlyAccess) { + temp = null; + } finally { + m = temp; + } + } else { + m = null; + } + if (m != null) { + jaxRsExecutorService = () -> { + try { + return (ExecutorService) m.invoke(null); + } catch (final ReflectiveOperationException reflectiveOperationException) { + throw new IllegalStateException(reflectiveOperationException.getMessage(), reflectiveOperationException); + } + }; + } else { + jaxRsExecutorService = ServerThreadPoolSupplier.builder() .name("server") - .config(config.get("server.executor-service")) + .config(serverConfig.get("server.executor-service")) .build(); + } } // redirect to the first page when root is accessed (if configured) diff --git a/pom.xml b/pom.xml index bd950db35..17d27d363 100644 --- a/pom.xml +++ b/pom.xml @@ -1456,5 +1456,34 @@ helidon-parent,helidon-dependencies,helidon-bom,helidon-se,helidon-mp,io.grpc,he + + loom + + 16-loom + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 16 + 16 + 16 + + + + org.apache.maven.plugins + maven-javadoc-plugin + + 16 + 16 + + + + + + diff --git a/webserver/jersey/src/main/java/io/helidon/webserver/jersey/AsyncExecutorProvider.java b/webserver/jersey/src/main/java/io/helidon/webserver/jersey/AsyncExecutorProvider.java index dca99048c..a1236cd96 100644 --- a/webserver/jersey/src/main/java/io/helidon/webserver/jersey/AsyncExecutorProvider.java +++ b/webserver/jersey/src/main/java/io/helidon/webserver/jersey/AsyncExecutorProvider.java @@ -16,7 +16,9 @@ package io.helidon.webserver.jersey; +import java.util.Objects; import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.function.Supplier; import io.helidon.common.configurable.ThreadPoolSupplier; @@ -30,23 +32,51 @@ class AsyncExecutorProvider implements ExecutorServiceProvider { private final Supplier executorServiceSupplier; AsyncExecutorProvider(Supplier supplier) { - this.executorServiceSupplier = supplier; + this.executorServiceSupplier = Objects.requireNonNull(supplier); } static ExecutorServiceProvider create(Config config) { - return new AsyncExecutorProvider(ThreadPoolSupplier.builder() + Config asyncExecutorServiceConfig = config.get("async-executor-service"); + final java.lang.reflect.Method m; + if (asyncExecutorServiceConfig.get("virtual-threads").asBoolean().orElse(false)) { + java.lang.reflect.Method temp = null; + try { + temp = Executors.class.getDeclaredMethod("newVirtualThreadExecutor"); + } catch (final ReflectiveOperationException notLoom) { + temp = null; + } finally { + m = temp; + } + } else { + m = null; + } + if (m != null) { + return new AsyncExecutorProvider(() -> { + try { + return (ExecutorService) m.invoke(null); + } catch (final ReflectiveOperationException reflectiveOperationException) { + throw new IllegalStateException(reflectiveOperationException.getMessage(), reflectiveOperationException); + } + }); + } else { + return new AsyncExecutorProvider(ThreadPoolSupplier.builder() .corePoolSize(1) .maxPoolSize(10) .prestart(false) .threadNamePrefix("helidon-jersey-async") - .config(config.get("async-executor-service")) + .config(asyncExecutorServiceConfig) .build()); + } } static ExecutorServiceProvider create(ExecutorService executor) { return new AsyncExecutorProvider(() -> executor); } + static ExecutorServiceProvider create(Supplier executorServiceSupplier) { + return new AsyncExecutorProvider(executorServiceSupplier); + } + @Override public ExecutorService getExecutorService() { return executorServiceSupplier.get();