Hi Yes you are welcome to create a JIRA and send a PR thanks
On Mon, Dec 9, 2024 at 7:37 PM Björn Beskow < bjorn.bes...@callistaenterprise.se> wrote: > Hi! > > I think there might be a regression problem in camel-platform-http-starter > introduced in 4.9.0 and 4.8.2 related to using Virtual Threads. If > spring.threads.virtual.enabled = true, a Camel application that uses > camel-platform-http-starter fails at startup with > > Caused by: java.lang.RuntimeException: No ThreadPoolTaskExecutor configured > at > org.apache.camel.component.platform.http.springboot.SpringBootPlatformHttpAutoConfiguration.lambda$springBootPlatformHttpEngine$1(SpringBootPlatformHttpAutoConfiguration.java:54) > ~[camel-platform-http-starter-4.9.0.jar:4.9.0] > at java.base/java.util.Optional.orElseThrow(Optional.java:403) > ~[na:na] > at > org.apache.camel.component.platform.http.springboot.SpringBootPlatformHttpAutoConfiguration.springBootPlatformHttpEngine(SpringBootPlatformHttpAutoConfiguration.java:54) > ~[camel-platform-http-starter-4.9.0.jar:4.9.0] > at > java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) > ~[na:na] > at java.base/java.lang.reflect.Method.invoke(Method.java:580) > ~[na:na] > at > org.springframework.beans.factory.support.SimpleInstantiationStrategy.lambda$instantiate$0(SimpleInstantiationStrategy.java:171) > ~[spring-beans-6.2.0.jar:6.2.0] > ... 24 common frames omitted > > unless a ThreadPoolTaskExecutor is explicitly configured. > > The problem seems to be caused by > https://github.com/apache/camel-spring-boot/pull/1278/commits/cd4deb0eda78054641056eb948a797b0a5a04560 > which now requires a ThreadPoolTaskExecutor to be configured: > > @Bean(name = "platform-http-engine") > @ConditionalOnMissingBean(PlatformHttpEngine.class) > public PlatformHttpEngine springBootPlatformHttpEngine(Environment > env) { > Executor executor; > > if (executors != null && !executors.isEmpty()) { > executor = executors.stream() > .filter(e -> e instanceof ThreadPoolTaskExecutor) > .findFirst() > .orElseThrow(() -> new RuntimeException("No > ThreadPoolTaskExecutor configured")); > } else { > throw new RuntimeException("No Executor configured"); > } > int port = Integer.parseInt(env.getProperty("server.port", > "8080")); > return new SpringBootPlatformHttpEngine(port, executor); > } > > If using virtual threads, the default auto-configuration of an executor > (defined in TaskExecutorConfiguration) instead uses a > SimpleAsyncTaskExecutor: > > class TaskExecutorConfigurations { > TaskExecutorConfigurations() { > } > > @Configuration( > proxyBeanMethods = false > ) > @ConditionalOnMissingBean({Executor.class}) > static class TaskExecutorConfiguration { > TaskExecutorConfiguration() { > } > > @Bean( > name = {"applicationTaskExecutor", "taskExecutor"} > ) > @ConditionalOnThreading(Threading.VIRTUAL) > SimpleAsyncTaskExecutor > applicationTaskExecutorVirtualThreads(SimpleAsyncTaskExecutorBuilder > builder) { > return builder.build(); > } > > @Lazy > @Bean( > name = {"applicationTaskExecutor", "taskExecutor"} > ) > @ConditionalOnThreading(Threading.PLATFORM) > ThreadPoolTaskExecutor > applicationTaskExecutor(ThreadPoolTaskExecutorBuilder > threadPoolTaskExecutorBuilder) { > return threadPoolTaskExecutorBuilder.build(); > } > } > > Hence no ThreadPoolTaskExecutor instance exists by default, and therefore > the exception is thrown. > > A simple workaround I use know is to explicitly configure a > ThreadPoolTaskExecutor instance (and instruct it to use virtual threads): > > @Configuration > public class VirtualThreadPoolTaskExecutorConfig { > > @Bean > @ConditionalOnMissingBean(AsyncTaskExecutor.class) > ThreadPoolTaskExecutor > threadPoolTaskExecutor(ThreadPoolTaskExecutorBuilder builder) { > ThreadPoolTaskExecutor threadPoolTaskExecutor = builder.build(); > threadPoolTaskExecutor.setVirtualThreads(true); > return threadPoolTaskExecutor; > } > > } > > But I think the original problem should be fixed, for instance by > accepting both a ThreadPoolTaskExecutor or a SimpleAsyncTaskExecutor in the > newly added code: > > public PlatformHttpEngine springBootPlatformHttpEngine(Environment > env) { > ... > .filter(e -> e instanceof ThreadPoolTaskExecutor || e > instanceof SimpleAsyncTaskExecutor) > … > > Not pretty, but works. > > Have I misunderstood something? > > If you agree it is a problem, I’ll submit a ticket and a pull request with > integration tests triggering the error together with the suggested fix > > /Björn > > -- Claus Ibsen ----------------- @davsclaus Camel in Action 2: https://www.manning.com/ibsen2