From c519d2d53c8f6da9f72bec4e6616e47a4bfa2804 Mon Sep 17 00:00:00 2001 From: Gaetano Piazzolla Date: Wed, 26 Apr 2023 23:36:54 +0200 Subject: [PATCH] BAEL-6085 - Working with Virtual Threads in Spring 6 (#13896) * BAEL-6085 - Working with Virtual Threads in Spring 6 * BAEL-6085 - jmeter test * BAEL-6085 | Virtual Thread Spring 6 * BAEL-6085 | Virtual Thread Spring 6 * BAEL-6085 | Virtual Thread Spring 6 * BAEL-6085 | Java 19 for compiling and executing * BAEL-6085 | Java 19 prop * BAEL-6085 | Java 19 prop * BAEL-6085 | Java 19 prop --- spring-boot-modules/spring-boot-3/pom.xml | 11 +- .../virtualthreads/VirtualThreadsApp.java | 13 ++ .../virtualthreads/config/ThreadConfig.java | 33 +++++ .../controller/LoadTestController.java | 23 ++++ .../controller/ThreadController.java | 16 +++ .../src/main/resources/application.yml | 4 +- .../src/test/HTTP Load Request .jmx | 125 ++++++++++++++++++ 7 files changed, 223 insertions(+), 2 deletions(-) create mode 100644 spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/VirtualThreadsApp.java create mode 100644 spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/config/ThreadConfig.java create mode 100644 spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/controller/LoadTestController.java create mode 100644 spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/controller/ThreadController.java create mode 100644 spring-boot-modules/spring-boot-3/src/test/HTTP Load Request .jmx diff --git a/spring-boot-modules/spring-boot-3/pom.xml b/spring-boot-modules/spring-boot-3/pom.xml index 03740e805f..8fe995ca91 100644 --- a/spring-boot-modules/spring-boot-3/pom.xml +++ b/spring-boot-modules/spring-boot-3/pom.xml @@ -116,6 +116,7 @@ org.springframework.boot spring-boot-maven-plugin + com.baeldung.virtualthreads.VirtualThreadsApp org.projectlombok @@ -131,15 +132,23 @@ org.springframework.boot spring-boot-maven-plugin + + org.apache.maven.plugins + maven-compiler-plugin + + --enable-preview + + + 19 1.5.2.Final 2.0.0 3.0.0-M7 com.baeldung.sample.TodoApplication - 5.14.0 + 5.14.0 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/VirtualThreadsApp.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/VirtualThreadsApp.java new file mode 100644 index 0000000000..159fa1c243 --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/VirtualThreadsApp.java @@ -0,0 +1,13 @@ +package com.baeldung.virtualthreads; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class VirtualThreadsApp { + + public static void main(String[] args) { + SpringApplication.run(VirtualThreadsApp.class, args); + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/config/ThreadConfig.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/config/ThreadConfig.java new file mode 100644 index 0000000000..7231ec0b94 --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/config/ThreadConfig.java @@ -0,0 +1,33 @@ +package com.baeldung.virtualthreads.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.task.AsyncTaskExecutor; +import org.springframework.core.task.support.TaskExecutorAdapter; +import org.springframework.scheduling.annotation.EnableAsync; + +import java.util.concurrent.Executors; + +@EnableAsync +@Configuration +@ConditionalOnProperty( + value = "spring.thread-executor", + havingValue = "virtual" +) +public class ThreadConfig { + + @Bean + public AsyncTaskExecutor applicationTaskExecutor() { + return new TaskExecutorAdapter(Executors.newVirtualThreadPerTaskExecutor()); + } + + @Bean + public TomcatProtocolHandlerCustomizer protocolHandlerVirtualThreadExecutorCustomizer() { + return protocolHandler -> { + protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor()); + }; + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/controller/LoadTestController.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/controller/LoadTestController.java new file mode 100644 index 0000000000..d99d3824a0 --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/controller/LoadTestController.java @@ -0,0 +1,23 @@ +package com.baeldung.virtualthreads.controller; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; + +@RestController +@RequestMapping("/load") +public class LoadTestController { + + private static final Logger LOG = LoggerFactory.getLogger(LoadTestController.class); + + @GetMapping + public void doSomething() throws InterruptedException { + LOG.info("hey, I'm doing something"); + Thread.sleep(1000); + } + +} diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/controller/ThreadController.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/controller/ThreadController.java new file mode 100644 index 0000000000..73b28ce9f0 --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/virtualthreads/controller/ThreadController.java @@ -0,0 +1,16 @@ +package com.baeldung.virtualthreads.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/thread") +public class ThreadController { + + @GetMapping("/name") + public String getThreadName() { + return Thread.currentThread().toString(); + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-3/src/main/resources/application.yml b/spring-boot-modules/spring-boot-3/src/main/resources/application.yml index 9a966a5bbd..5f9031bc9e 100644 --- a/spring-boot-modules/spring-boot-3/src/main/resources/application.yml +++ b/spring-boot-modules/spring-boot-3/src/main/resources/application.yml @@ -14,8 +14,10 @@ spring: properties: hibernate: dialect: org.hibernate.dialect.H2Dialect + thread-executor: standard + # Custom Properties cors: allow: origins: ${CORS_ALLOWED_ORIGINS:*} - credentials: ${CORS_ALLOW_CREDENTIALS:false} + credentials: ${CORS_ALLOW_CREDENTIALS:false} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-3/src/test/HTTP Load Request .jmx b/spring-boot-modules/spring-boot-3/src/test/HTTP Load Request .jmx new file mode 100644 index 0000000000..bbd02cecbe --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/test/HTTP Load Request .jmx @@ -0,0 +1,125 @@ + + + + + + false + true + false + + + + + + + + stoptest + + false + -1 + + 1000 + 10 + true + 100 + + true + + + + + + + localhost + 8080 + + + /load + GET + true + false + true + false + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + +