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 + 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