Files
Claude c418589251 Add custom-starter module: a Boot 4 auto-configuration starter with conditions, metadata and runner tests
Two-jar starter (autoconfigure + starter), a demo app, and 17 captured transcripts
covering AutoConfiguration.imports, @ConditionalOn*, ordering, optional Jackson 3
integration, configuration metadata and the Boot 4 module split.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Uu7q8vPeREyT4218EJPzz1
2026-09-24 06:53:07 +00:00

4.7 KiB

custom-starter

A Spring Boot 4 starter written from scratch, and the application that uses it. Companion to Write Your Own Spring Boot 4 Starter: Auto-Configuration, @Conditional and Properties.

The starter provides one thing, a Masker that hides all but the last few characters of a value, plus an optional Jackson integration that writes a Sensitive value masked. The subject is the packaging, not the masking.

Spring Boot 4.1.1 (parent pom, published 20 Aug 2026)
Spring Framework 7.0.9
Java 25
Maven 3.9

There is no docs/ folder. The explanations live in the article, in collapsible sections next to the paragraph each one extends, and every console block in the article is quoted from a file in output/.

Layout

Module What it is
masker-spring-boot-autoconfigure/ MaskerAutoConfiguration, MaskerJacksonAutoConfiguration, MaskerProperties, the AutoConfiguration.imports file, the configuration metadata, and the tests
masker-spring-boot-starter/ The dependency an application adds. No code, only a pom
masker-demo/ An application that adds the starter and nothing else

masker-spring-boot-autoconfigure/src/test/java/com/ankurm/traps/ holds auto-configurations that are wrong on purpose. src/broken/ holds a source file that is made not to compile on purpose. Neither is part of the shipped jar.

Run it

export JAVA_HOME=/path/to/jdk-25
./scripts/run-all.sh          # tests, then the jar and failure captures: regenerates all of output/
mvn -B test                   # only the tests

Captured output

File What it shows Made by
01 the auto-configuration with no properties and no user beans MaskerAutoConfigurationTests
02 masker.* properties and masker.enabled=false MaskerAutoConfigurationTests
03 @ConditionalOnMissingBean backing off, and the registration order that decides it MaskerAutoConfigurationTests
04 the Jackson module registered, a Sensitive written masked, the recorded condition outcomes JacksonIntegrationTests
05 Jackson hidden with FilteredClassLoader: no failure, no module JacksonIntegrationTests
06 @ConditionalOnBean with and without an ordering constraint, and the sorted order ConditionTrapTests
07 @ConditionalOnClass on a @Bean method, on a classpath with no Jackson capture-jar-facts.sh
08 an auto-configuration missing from the imports file: passes a runner test, absent everywhere ForgottenImportsEntryTests
09 ImportCandidates, the guard test for the omission ForgottenImportsEntryTests
10 an application with only the starter dependency, and Boot's recorded conditions DemoApplicationTests
11 the same application with properties, then switched off DemoApplicationTests
12 what is in the two jars, and what the starter pulls in capture-jar-facts.sh
13 the generated and the hand-written configuration metadata, and the auto-configuration conditions metadata capture-jar-facts.sh
14 Boot 4's split of spring-boot-autoconfigure, and the Boot 3 import that no longer compiles capture-jar-facts.sh
15 the processor path failing when the version is taken from your own parent capture-jar-facts.sh
17 which Boot 4.1.1 jar holds each class this starter imports capture-jar-facts.sh
16 @ConditionalOnProperty without matchIfMissing ConditionTrapTests

Transcripts are deterministic; only build-directory paths are rewritten, to <custom-starter>.