# kotlin Companion project for the article **[Kotlin with Spring Boot 4.1: Null Safety, Coroutines, and What Java Developers Get Wrong](https://ankurm.com/)** on **[ankurm.com](https://ankurm.com)**. Every console block quoted in the article came out of `docs/output/`. 03-08 are raw `curl` captures against a running instance; 01, 02 and 09 are real build/startup transcripts. `BookControllerTest.kt` turns the null-safety claims into assertions, so a change in Spring, Kotlin or JSpecify behaviour breaks the build, not just the prose. There is deliberately **no `docs/NN-topic.md` chapter folder**: the deeper material lives in collapsible "going deeper" sections inside the article itself, next to the paragraph each one extends. `docs/output/` (captured transcripts) is the one thing that still lives under `docs/`. ## Versions | | | |---|---| | Spring Boot | 4.1.1 | | Spring Framework | 7.0.9 | | Kotlin | 2.3.21 (Spring Boot 4.1.1's own managed version; latest actual GA is 2.4.20 — see the article) | | kotlinx.coroutines | 1.10.2 | | jackson-module-kotlin | 2.22.3 (not BOM-managed; pin it explicitly) | | JSpecify | 1.0.0 | | JDK | 25 (GraalVM CE 25.4.4.1.1) | | Maven | 3.9 | ## Quickstart ```bash export JAVA_HOME=/path/to/jdk-25 mvn test # runs BookControllerTest, re-verifying every null-safety claim mvn spring-boot:run # starts the app on :8090 with 3 seeded books ``` ## What's demonstrated | Area | Where | |---|---| | allopen/noarg via the `spring`/`jpa` kotlin compiler plugins | `pom.xml`'s `kotlin-maven-plugin` config; `BookService.kt`, `Book.kt`, `Application.kt` | | Real build failure without the `spring` plugin (`@Configuration class may not be final`, then `@Bean method must not be private or final`) | `docs/output/01-build-failure-without-allopen.txt` | | Clean startup with both plugins restored | `docs/output/02-fixed-startup.txt` | | `suspend fun` / `Flow` controller methods under plain `spring-boot-starter-webmvc` (Tomcat, not WebFlux) | `BookController.kt` (`/books`, `/books/flow`) | | Which thread actually resumes a suspended controller method | `/books/thread-check`, `docs/output/05-thread-check.txt` | | Kotlin platform types (`String!`) for un-annotated Java APIs | `legacy/LegacyJavaApi.java`, `/books/null-demo/legacy/{id}`, `docs/output/06-null-demo-legacy.txt` | | JSpecify `@NullMarked`/`@Nullable` interop, and that it is a static contract, not a runtime guarantee | `legacy/NullMarkedJavaApi.java`, `/books/null-demo/jspecify/{id}`, `/books/null-demo/jspecify-honest/{id}`, `docs/output/07-08` | | Mixed Kotlin+Java compilation in one Maven module | `pom.xml` (`kotlin-maven-plugin` compiles `src/main/kotlin` + `src/main/java`; `maven-compiler-plugin`'s `default-compile`/`default-testCompile` disabled, `java-compile` picks up the default `src/main/java`) | | `TestRestTemplate` no longer shipping in Spring Boot 4.1's `spring-boot-test` module | `docs/output/09-no-testresttemplate.txt`, `BookControllerTest.kt` (plain `java.net.http.HttpClient` instead) | ## Captured output | File | What it shows | |---|---| | `01-build-failure-without-allopen.txt` | both real failures when the `spring` compiler plugin is removed | | `02-fixed-startup.txt` | clean startup once it's restored | | `03-books-endpoint.txt` | `GET /books`, a `suspend fun` controller method, real JSON | | `04-books-flow-endpoint.txt` | `GET /books/flow`, a `Flow` controller method | | `05-thread-check.txt` | three runs of `/books/thread-check`: before/after thread names across a real suspension point | | `06-null-demo-legacy.txt` | the platform-type NPE, with no compiler hint anywhere, plus its stack trace | | `07-null-demo-jspecify.txt` | the `@NullMarked` Java method that still NPEs, plus its stack trace | | `08-null-demo-jspecify-honest.txt` | the `@Nullable`-annotated method the Kotlin compiler forces a null check on — no NPE | | `09-no-testresttemplate.txt` | `TestRestTemplate` verified absent from `spring-boot-test-4.1.1.jar` | Endpoints default to `http://localhost:8090`. H2 is in-memory (`jdbc:h2:mem:kotlindemo`), reseeded on every restart with three books, one of them with a `null` title.