diff --git a/pom.xml b/pom.xml
index eea18ce..364e48e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -60,6 +60,8 @@
podman-deployment
spring-boot-batch
application-events
+ spring-virtual-threads-example
+ spring-virtual-threads-example/spring-webflux-example
spring-boot-examples
https://howtodoinjava.com
@@ -78,10 +80,6 @@
-
- org.springframework.boot
- spring-boot-starter-web
-
org.projectlombok
lombok
diff --git a/spring-virtual-threads-example/pom.xml b/spring-virtual-threads-example/pom.xml
new file mode 100644
index 0000000..3f31996
--- /dev/null
+++ b/spring-virtual-threads-example/pom.xml
@@ -0,0 +1,26 @@
+
+
+ 4.0.0
+
+ com.howtodoinjava.demo
+ spring-boot-examples
+ 1.0-SNAPSHOT
+
+
+ com.howtodoinjava.virtual.threads.example
+ spring-virtual-threads-example
+ pom
+
+ spring-boot-example
+
+
+
+ 21
+ 21
+ 21
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/spring-virtual-threads-example/spring-boot-example/pom.xml b/spring-virtual-threads-example/spring-boot-example/pom.xml
new file mode 100644
index 0000000..eab283f
--- /dev/null
+++ b/spring-virtual-threads-example/spring-boot-example/pom.xml
@@ -0,0 +1,74 @@
+
+
+ 4.0.0
+
+ com.howtodoinjava.virtual.threads.example
+ spring-virtual-threads-example
+ 1.0-SNAPSHOT
+
+
+ spring-boot-example
+
+
+ 21
+ 21
+ 21
+ UTF-8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.apache.commons
+ commons-lang3
+ 3.12.0
+
+
+ com.h2database
+ h2
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+ provided
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ --enable-preview
+
+
+ 21
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-virtual-threads-example/spring-boot-example/src/main/java/com/howtodoinjava/virtual/threads/example/Main.java b/spring-virtual-threads-example/spring-boot-example/src/main/java/com/howtodoinjava/virtual/threads/example/Main.java
new file mode 100644
index 0000000..19137ce
--- /dev/null
+++ b/spring-virtual-threads-example/spring-boot-example/src/main/java/com/howtodoinjava/virtual/threads/example/Main.java
@@ -0,0 +1,26 @@
+package com.howtodoinjava.virtual.threads.example;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer;
+import org.springframework.context.annotation.Bean;
+
+import java.util.concurrent.Executors;
+
+@Slf4j
+@SpringBootApplication
+public class Main {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Main.class, args);
+ }
+
+ @Bean
+ public TomcatProtocolHandlerCustomizer> protocolHandlerVirtualThreadExecutorCustomizer() {
+ return protocolHandler -> {
+ log.info("Configuring " + protocolHandler + " to use VirtualThreadPerTaskExecutor");
+ protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
+ };
+ }
+}
\ No newline at end of file
diff --git a/spring-virtual-threads-example/spring-boot-example/src/main/java/com/howtodoinjava/virtual/threads/example/controller/TestController.java b/spring-virtual-threads-example/spring-boot-example/src/main/java/com/howtodoinjava/virtual/threads/example/controller/TestController.java
new file mode 100644
index 0000000..f1e65e2
--- /dev/null
+++ b/spring-virtual-threads-example/spring-boot-example/src/main/java/com/howtodoinjava/virtual/threads/example/controller/TestController.java
@@ -0,0 +1,37 @@
+package com.howtodoinjava.virtual.threads.example.controller;
+
+import com.howtodoinjava.virtual.threads.example.model.Product;
+import com.howtodoinjava.virtual.threads.example.repository.ProductRepository;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.RandomUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@RestController
+public class TestController {
+
+ @Autowired
+ ProductRepository productRepository;
+
+ @GetMapping("/thread")
+ public List checkThread() throws InterruptedException {
+ Thread.sleep(1000);
+ return productRepository.findAll();
+ }
+
+ @PostMapping("/save")
+ public String saveProduct() throws InterruptedException {
+ for(int i = 0; i < 1000; i++){
+ Product product = new Product();
+ product.setProductName(RandomStringUtils.randomAlphanumeric(5));
+ product.setPrice(RandomUtils.nextLong(10,1000));
+ product.setPrice(1L);
+ productRepository.save(product);
+ }
+ return "Success";
+ }
+}
\ No newline at end of file
diff --git a/spring-virtual-threads-example/spring-boot-example/src/main/java/com/howtodoinjava/virtual/threads/example/model/Product.java b/spring-virtual-threads-example/spring-boot-example/src/main/java/com/howtodoinjava/virtual/threads/example/model/Product.java
new file mode 100644
index 0000000..a92b1fe
--- /dev/null
+++ b/spring-virtual-threads-example/spring-boot-example/src/main/java/com/howtodoinjava/virtual/threads/example/model/Product.java
@@ -0,0 +1,24 @@
+package com.howtodoinjava.virtual.threads.example.model;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+
+@Getter
+@Setter
+@ToString
+@Entity
+public class Product {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+ private String productName;
+ private Long price;
+
+}
\ No newline at end of file
diff --git a/spring-virtual-threads-example/spring-boot-example/src/main/java/com/howtodoinjava/virtual/threads/example/repository/ProductRepository.java b/spring-virtual-threads-example/spring-boot-example/src/main/java/com/howtodoinjava/virtual/threads/example/repository/ProductRepository.java
new file mode 100644
index 0000000..39aca84
--- /dev/null
+++ b/spring-virtual-threads-example/spring-boot-example/src/main/java/com/howtodoinjava/virtual/threads/example/repository/ProductRepository.java
@@ -0,0 +1,7 @@
+package com.howtodoinjava.virtual.threads.example.repository;
+
+import com.howtodoinjava.virtual.threads.example.model.Product;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface ProductRepository extends JpaRepository {
+}
\ No newline at end of file
diff --git a/spring-virtual-threads-example/spring-boot-example/src/main/resources/application.yml b/spring-virtual-threads-example/spring-boot-example/src/main/resources/application.yml
new file mode 100644
index 0000000..30fab2b
--- /dev/null
+++ b/spring-virtual-threads-example/spring-boot-example/src/main/resources/application.yml
@@ -0,0 +1,21 @@
+spring:
+ datasource:
+ maxIdle: 1
+ url: jdbc:h2:mem:mydb
+ username: sa
+ password: password
+ driverClassName: org.h2.Driver
+ hikari:
+ connection-timeout: 60000
+ maximum-pool-size: 10
+ minimum-idle: 5
+ h2:
+ console:
+ enabled: true
+ jpa:
+ spring.jpa.database-platform: org.hibernate.dialect.H2Dialect
+ generate-ddl: true
+ hibernate:
+ ddl-auto: create
+ format_sql: true
+ show-sql: true
\ No newline at end of file
diff --git a/spring-virtual-threads-example/spring-webflux-example/pom.xml b/spring-virtual-threads-example/spring-webflux-example/pom.xml
new file mode 100644
index 0000000..7e7cbd1
--- /dev/null
+++ b/spring-virtual-threads-example/spring-webflux-example/pom.xml
@@ -0,0 +1,58 @@
+
+
+ 4.0.0
+
+ com.howtodoinjava.demo
+ spring-boot-examples
+ 1.0-SNAPSHOT
+ ../../pom.xml
+
+
+ com.howtodoinjava.virtual.threads.example
+ spring-webflux-example
+
+
+ 21
+ 21
+ UTF-8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-r2dbc
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+ io.r2dbc
+ r2dbc-h2
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ io.projectreactor
+ reactor-test
+ test
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+ provided
+
+
+ org.apache.commons
+ commons-lang3
+
+
+
+
\ No newline at end of file
diff --git a/spring-virtual-threads-example/spring-webflux-example/src/main/java/com/howtodoinjava/virtual/threads/example/Main.java b/spring-virtual-threads-example/spring-webflux-example/src/main/java/com/howtodoinjava/virtual/threads/example/Main.java
new file mode 100644
index 0000000..f10131c
--- /dev/null
+++ b/spring-virtual-threads-example/spring-webflux-example/src/main/java/com/howtodoinjava/virtual/threads/example/Main.java
@@ -0,0 +1,19 @@
+package com.howtodoinjava.virtual.threads.example;
+
+import io.r2dbc.spi.ConnectionFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.r2dbc.connection.init.ConnectionFactoryInitializer;
+import org.springframework.r2dbc.connection.init.ResourceDatabasePopulator;
+import org.springframework.web.reactive.config.EnableWebFlux;
+
+@EnableWebFlux
+@SpringBootApplication
+public class Main {
+ public static void main(String[] args) {
+ SpringApplication.run(Main.class, args);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-virtual-threads-example/spring-webflux-example/src/main/java/com/howtodoinjava/virtual/threads/example/webflux/controller/WebfluxHomeController.java b/spring-virtual-threads-example/spring-webflux-example/src/main/java/com/howtodoinjava/virtual/threads/example/webflux/controller/WebfluxHomeController.java
new file mode 100644
index 0000000..67c8aba
--- /dev/null
+++ b/spring-virtual-threads-example/spring-webflux-example/src/main/java/com/howtodoinjava/virtual/threads/example/webflux/controller/WebfluxHomeController.java
@@ -0,0 +1,40 @@
+package com.howtodoinjava.virtual.threads.example.webflux.controller;
+
+import com.howtodoinjava.virtual.threads.example.webflux.model.Product;
+import com.howtodoinjava.virtual.threads.example.webflux.repository.ProductRepo;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.RandomUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+@RestController
+@RequestMapping("/webflux")
+public class WebfluxHomeController {
+
+ @Autowired
+ ProductRepo productRepository;
+
+ @GetMapping("/thread")
+ public Flux webfluxThreadProducts() throws InterruptedException {
+ Thread.sleep(1000);
+ return productRepository.findAll();
+ }
+
+ @PostMapping("/save")
+ public String webfluxSaveProduct() throws InterruptedException {
+ for(int i = 0; i < 1000; i++){
+ Product product = new Product();
+ product.setProductName(RandomStringUtils.randomAlphanumeric(5));
+ product.setPrice(RandomUtils.nextLong(10,1000));
+ product.setPrice(1L);
+ Mono savedData = productRepository.save(product);
+ System.out.println(savedData.toString());
+ }
+ return "Success";
+ }
+}
\ No newline at end of file
diff --git a/spring-virtual-threads-example/spring-webflux-example/src/main/java/com/howtodoinjava/virtual/threads/example/webflux/model/Product.java b/spring-virtual-threads-example/spring-webflux-example/src/main/java/com/howtodoinjava/virtual/threads/example/webflux/model/Product.java
new file mode 100644
index 0000000..50ee7f5
--- /dev/null
+++ b/spring-virtual-threads-example/spring-webflux-example/src/main/java/com/howtodoinjava/virtual/threads/example/webflux/model/Product.java
@@ -0,0 +1,21 @@
+package com.howtodoinjava.virtual.threads.example.webflux.model;
+
+
+import lombok.*;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.relational.core.mapping.Table;
+
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+@Table("product")
+public class Product {
+
+ @Id
+ private Long id;
+ private String productName;
+ private Long price;
+
+}
\ No newline at end of file
diff --git a/spring-virtual-threads-example/spring-webflux-example/src/main/java/com/howtodoinjava/virtual/threads/example/webflux/repository/ProductRepo.java b/spring-virtual-threads-example/spring-webflux-example/src/main/java/com/howtodoinjava/virtual/threads/example/webflux/repository/ProductRepo.java
new file mode 100644
index 0000000..dad8ff2
--- /dev/null
+++ b/spring-virtual-threads-example/spring-webflux-example/src/main/java/com/howtodoinjava/virtual/threads/example/webflux/repository/ProductRepo.java
@@ -0,0 +1,9 @@
+package com.howtodoinjava.virtual.threads.example.webflux.repository;
+
+import com.howtodoinjava.virtual.threads.example.webflux.model.Product;
+import org.springframework.data.repository.reactive.ReactiveCrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ProductRepo extends ReactiveCrudRepository {
+}
\ No newline at end of file
diff --git a/spring-virtual-threads-example/spring-webflux-example/src/main/resources/application.yml b/spring-virtual-threads-example/spring-webflux-example/src/main/resources/application.yml
new file mode 100644
index 0000000..eda3c37
--- /dev/null
+++ b/spring-virtual-threads-example/spring-webflux-example/src/main/resources/application.yml
@@ -0,0 +1,15 @@
+logging:
+ level:
+ root: DEBUG
+spring:
+ r2dbc:
+ url: r2dbc:h2:mem:///mydb?options=DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+ name: sa
+ password:
+ main:
+ allow-bean-definition-overriding: true
+ web-application-type: reactive
+
+ h2:
+ console:
+ enabled: true
\ No newline at end of file
diff --git a/spring-virtual-threads-example/spring-webflux-example/src/main/resources/schema.sql b/spring-virtual-threads-example/spring-webflux-example/src/main/resources/schema.sql
new file mode 100644
index 0000000..d41de2b
--- /dev/null
+++ b/spring-virtual-threads-example/spring-webflux-example/src/main/resources/schema.sql
@@ -0,0 +1,6 @@
+create table product
+(
+ id UUID DEFAULT RANDOM_UUID() PRIMARY KEY,
+ product_name varchar(50),
+ price integer
+);
\ No newline at end of file