1
0

Add every example from the post, plus edge cases, to the companion repo

Full companion repo for the ankurm.com post "Spring Security Context Propagation:
The Complete Guide" -- every code example the post discusses now has a corresponding
runnable, verified demo (JDK 25, Spring Security 7.1.1, Spring Boot 4.1.1 dependency
versions), not just the virtual-thread/structured-concurrency sections:

- Demo1PlainThreadLocal: InheritableThreadLocal across thread models (no Spring)
- Demo2AsyncVirtualThreads: @Async on a virtual-thread SimpleAsyncTaskExecutor
  (DelegatingSecurityContextExecutor vs ContextPropagatingTaskDecorator)
- Demo3StructuredConcurrency: StructuredTaskScope.fork() propagation
- Demo4ExecutorWrapping: DelegatingSecurityContextExecutorService/Executor/
  AsyncTaskExecutor on a classic pooled platform-thread executor -- the post's
  "Using @Async" / "Using ExecutorService" / "Using CompletableFuture" sections
- Demo5ReactiveContext: ReactiveSecurityContextHolder vs. ThreadLocal across a
  Reactor scheduler hop -- the post's WebFlux/getProfile() section
- Demo6ScheduledSystemIdentity: DelegatingSecurityContextTaskScheduler's actual
  per-call capture semantics (confirmed via bytecode before writing the demo) and
  the createSystemContext() pattern -- the post's scheduled-tasks section
- Demo7ServletFilterPersistence: SecurityContextHolderFilter (load-only) vs.
  SecurityContextPersistenceFilter (load+auto-save), against real filter instances
  and a real HttpSession -- the post's servlet-environment section
- SecurityContextPropagationContractTest: 10 JUnit tests pinning the above as
  assertions instead of printed lines, including a TestSecurityContextHolder-based
  test reproducing the post's own "Testing Security Context Propagation" section

Thirteen edge cases discovered along the way are indexed in docs/08 with links into
the chapter that reproduces each one -- a reused pool worker NOT leaking under the
Delegating* wrappers (unlike Demo1's InheritableThreadLocal), the common ForkJoinPool
trap, why there's no DelegatingSecurityContextStructuredTaskScope and never will be,
a real NullPointerException from Reactor's map() hit while writing the reactive test,
per-call (not per-construction) context capture in DelegatingSecurityContextTaskScheduler,
and the precise load-vs-save split between the two servlet filters, among others.

docs/01-08 are numbered, cross-linked chapters with prev/next navigation; README
indexes all demos, chapters, captured output, and the edge-case list. scripts/run-all.sh
regenerates every docs/output/*.txt and the test suite output from one command.
This commit is contained in:
2026-08-24 21:48:47 +05:30
committed by Claude
commit 9f950bffa9
28 changed files with 2009 additions and 0 deletions

33
scripts/run-all.sh Executable file
View File

@@ -0,0 +1,33 @@
#!/usr/bin/env bash
# Compiles and runs all seven demos plus the JUnit contract test suite, regenerating
# docs/output/*.txt. Requires JDK 25 (StructuredTaskScope is a preview API through JDK 25 /
# JEP 505).
set -euo pipefail
cd "$(dirname "$0")/.."
mvn -q dependency:build-classpath -Dmdep.outputFile=cp.txt
CP=$(cat cp.txt)
rm -rf target/classes
mkdir -p target/classes docs/output
javac --release 25 --enable-preview -cp "$CP" -d target/classes $(find src/main -name '*.java')
for demo in Demo1PlainThreadLocal Demo2AsyncVirtualThreads Demo3StructuredConcurrency \
Demo4ExecutorWrapping Demo5ReactiveContext Demo6ScheduledSystemIdentity \
Demo7ServletFilterPersistence; do
num=$(echo "$demo" | grep -o '^Demo[0-9]*' | grep -o '[0-9]*')
out="docs/output/demo${num}.txt"
echo "Running $demo -> $out"
java --enable-preview -cp "target/classes:$CP" "com.ankurm.vt.$demo" \
| grep -v '^Picked up JAVA_TOOL_OPTIONS' | tee "$out"
done
echo "Running JUnit contract test suite -> docs/output/tests.txt"
mvn -q test > /tmp/mvn-test-raw.txt 2>&1 || true
{
echo "mvn test -- SecurityContextPropagationContractTest (10 tests pinning the claims each demo prints above)"
echo
cat target/surefire-reports/com.ankurm.vt.SecurityContextPropagationContractTest.txt
} > docs/output/tests.txt
cat docs/output/tests.txt
rm -f /tmp/mvn-test-raw.txt