# 1. Enabling virtual threads on Spring Boot 4.1 [README](../README.md) | Next: [02-benchmark-methodology.md](02-benchmark-methodology.md) Source: [`application.yml`](../src/main/resources/application.yml), [`DemoController.java`](../src/main/java/com/ankurm/vthreads/DemoController.java). Test: [`ThreadTypeTest.java`](../src/test/java/com/ankurm/vthreads/ThreadTypeTest.java). Transcript: [`docs/output/00-thread-type-confirmation.txt`](output/00-thread-type-confirmation.txt). ## Still one property `spring.threads.virtual.enabled=true` is unchanged since Boot 3.2 and still the whole configuration surface for most apps on Boot 4.1. It requires JDK 21+; this repo runs it on JDK 25. ## What actually flips Confirmed against a real running embedded server, not by reading the reference docs: ``` enabled=false -> Thread: Thread[#9711,http-nio-auto-5-exec-1,5,main] | Virtual: false enabled=true -> Thread: VirtualThread[#9737,tomcat-handler-0]/runnable@ForkJoinPool-1-worker-2 | Virtual: true ``` The platform-thread name prefix changed between the Boot 3 era and this repo's Boot 4.1 run (`http-nio-auto-5-exec-1` here vs. the `http-nio-8080-exec-3` shape in the older post) because this test binds to `server.port=0` (a random port) rather than a fixed 8080 -- Tomcat's connector-name-derived thread prefix reflects that. Cosmetic, but worth not being surprised by if your own logs look different from either example. ## Test infrastructure trap worth knowing about Setting the property via `SpringApplicationBuilder.properties(...)` and expecting it to win over `application.yml` is a real bug this repo hit while building the benchmark below: `.properties(...)` binds to Spring's **`defaultProperties`** source, which has the *lowest* precedence of any property source Spring Boot recognizes -- lower than `application.yml`, which had `spring.threads.virtual.enabled: false` as its own explicit default. The fix was passing it as a command-line-style argument to `run(...)` instead (`"--spring.threads.virtual.enabled=" + value`), which binds at the highest precedence. See [`LoadBenchmarkTest.java`](../src/test/java/com/ankurm/vthreads/LoadBenchmarkTest.java) for where this was caught -- the first draft of the CPU-bound benchmark below silently ran both scenarios on platform threads and reported a difference that didn't exist. Next: [02-benchmark-methodology.md](02-benchmark-methodology.md).