ApplicationRunner is a custom Gradle task in buildSrc used exclusively by the documentation build. It launches a Spring Boot application as a child process, waits for a specific log line to appear, captures the combined stdout/stderr to a file, and then normalizes the output so that machine-specific values (ports, paths, usernames, PIDs) are replaced with stable, canonical values before the file is embedded in the reference documentation.
This page covers the implementation detail of the task itself. For the broader documentation pipeline that registers and wires these tasks together, see Documentation Generation Pipeline.
ApplicationRunner extends Gradle's DefaultTask. When executed, it:
java -cp <classpath> <mainClass> [args...] command using the current JVM.expectedLogging string appears in any line, or until 60 seconds elapse.Sources: buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java51-115
| Property | Gradle annotation | Type | Description |
|---|---|---|---|
output | @OutputFile | RegularFileProperty | File where process stdout+stderr are written |
classpath | @Classpath | FileCollection | JVM classpath used to launch the application |
mainClass | @Input | Property<String> | Fully-qualified main class name |
args | @Input | ListProperty<String> | Additional command-line arguments |
expectedLogging | @Input | Property<String> | Substring to wait for in the output |
normalizations | @Input | MapProperty<String, String> | Regex → replacement pairs (package-private) |
applicationJar | @Input | Property<String> | Canonical jar path used in normalized startup banner; defaults to /opt/apps/myapp.jar |
Sources: buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java59-84
Diagram: Task execution sequence
Sources: buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java96-115
The runApplication() method buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java96-115 assembles the command as follows:
Jvm.current().getExecutable("java") — resolves the JVM binary from Gradle's current toolchain.-cp <classpath> — all files in the FileCollection joined by the platform path separator.getMainClass().get() — the fully-qualified entry point.getArgs().get().Both redirectOutput and redirectError are directed to the same output file, so the captured log contains interleaved stdout and stderr exactly as they would appear on a terminal.
Sources: buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java96-115
awaitLogging)awaitLogging buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java117-131 polls the output file in a tight loop for up to 60 seconds:
Files.readAllLines and checks each line for expectedLogging as a substring.IllegalStateException is thrown immediately rather than waiting for the timeout.IllegalStateException reports the timeout.This design handles slow startup without spinning indefinitely.
Sources: buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java117-131
After the process is destroyed, normalizeLogging() rewrites the output file with stable values so that documentation output is reproducible across machines and environments.
Diagram: Normalization data flow
Sources: buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java143-194
Every invocation always applies one normalization defined inline in normalize(List<String>) buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java155-165:
| Pattern | Replacement |
|---|---|
(Starting .* using Java .* with PID [\d]+ \().*( started by ).*(in ).*(\\)) | $1<applicationJar>$2myuser$3/opt/apps/$4 |
This sanitizes the Spring Boot startup banner line so that the jar path, user, and working directory are always the canonical documentation values.
The private normalize(List<String>, Pattern, String) method buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java167-184 tracks a matched flag. If a normalization pattern does not match any line in the output, reportUnmatchedNormalization buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java186-194 throws an IllegalStateException that includes the full output. This prevents patterns from silently becoming stale if the application log format changes.
Sources: buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java167-194
Two public methods pre-populate the normalizations map with common Spring Boot patterns:
Diagram: Convenience methods and the patterns they register
| Method | Pattern | Canonical replacement |
|---|---|---|
normalizeTomcatPort() | (Tomcat started on port )[\d]+( \(http\)) | $18080$2 |
normalizeTomcatPort() | (Tomcat initialized with port )[\d]+( \(http\)) | $18080$2 |
normalizeLiveReloadPort() | (LiveReload server is running on port )[\d]+ | $135729 |
Both methods use Java regex capture groups ($1, $2) to preserve the surrounding text while replacing only the dynamic port number with a fixed value (8080 for Tomcat, 35729 for LiveReload).
Sources: buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java86-93
Diagram: ApplicationRunner in the buildSrc class hierarchy and task graph
Sources: buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java51-196
| Condition | Exception | Message |
|---|---|---|
Process exits before expectedLogging appears | IllegalStateException | "Process exited before '<expectedLogging>' was logged" |
60 seconds pass without expectedLogging appearing | IllegalStateException | "'<expectedLogging>' was not logged within 60 seconds" |
| A normalization pattern matches no output line | IllegalStateException | Pattern + full output listing |
Sources: buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java117-131 buildSrc/src/main/java/org/springframework/boot/build/docs/ApplicationRunner.java186-194
Refresh this wiki