Spring Boot Application Foundations
Latest stable Based on Bluetape4k release 1.11.0
What it provides
Section titled “What it provides”bluetape4k-spring-boot-core collects small adapters that otherwise recur across Spring Framework and Spring Boot applications. It provides bean and merged-annotation lookup, profile and property access, coroutine calls for RestClient, WebFlux request context and DataBuffer helpers, standard error responses, Micrometer Observation helpers, and dedicated WebClient resource configuration.
It does not replace Spring Boot. Spring Boot and the application still configure the application context, HTTP client implementation, JSON converters, Actuator exporters, security, and transactions. This module adds Kotlin extensions and explicitly imported configuration on top of those facilities.
Decide before adopting it
Section titled “Decide before adopting it”- Separate Spring Context helpers from HTTP and WebFlux helpers. Do not treat the whole artifact as an application framework.
- Adding
VirtualThreadAutoConfigurationto the classpath does not enable it. Import it explicitly with@Import. HttpRequestCapturerandApiExceptionHandlermust also be inside the application’s component-scan range.RestClientis blocking. The suspend extensions run blocking calls interruptibly onDispatchers.IO; they do not turn the client into reactive I/O.- A dedicated WebClient event loop or controller coroutine scope introduces an ownership and shutdown obligation.
If you only need Spring Data R2DBC coroutine extensions, start with bluetape4k-spring-boot-r2dbc. For JDBC and transaction helpers, see bluetape4k-jdbc.
Add the dependency
Section titled “Add the dependency”Consumers manage only the bluetape4k-dependencies BOM version. Add the Spring starter that supplies the capability used by the application.
dependencies { implementation(platform("io.github.bluetape4k:bluetape4k-dependencies:<version>")) implementation("io.github.bluetape4k:bluetape4k-spring-boot-core")
implementation("org.springframework.boot:spring-boot-starter-webflux") // choose for the APIs you use}Most Web, WebFlux, Spring Data, Micrometer, and Netty dependencies of this module are compileOnly. The matching starter or library must be present at runtime before its APIs can be used.
First examples
Section titled “First examples”Use reified extensions for Spring merged-annotation lookup:
val mapping = handlerMethod.findMergedAnnotationOrNull<RequestMapping>()val isMapped = handlerMethod.hasMergedAnnotation<RequestMapping>()Call a blocking RestClient from a coroutine service like this:
class UserClient( private val client: RestClient,) { suspend fun find(id: Long): User = client.suspendGet("/users/$id", MediaType.APPLICATION_JSON)}suspendGet uses runInterruptible(Dispatchers.IO). Coroutine cancellation can interrupt the client thread, but whether that aborts the request depends on the ClientHttpRequestFactory.
API by task
Section titled “API by task”| Task | API | Boundary to keep visible |
|---|---|---|
| Find merged annotations | findMergedAnnotationOrNull, hasMergedAnnotation | Preserves Spring meta-annotation and @AliasFor semantics. |
| Look up beans | BeanFactory.get, findOrNull family | Missing beans may become null; ambiguous beans remain errors. |
| Declare profiles | LocalProfile, DevelopProfile, ProductionProfile, and peers | Aliases Spring @Profile; does not create a property source. |
| Read properties | PropertyResolver.getAs, getRequiredPropertyAs | Uses Spring conversion; a missing required value fails. |
| Call blocking HTTP | restClientOf, httpGet, suspendGet family | The application owns request factory, converters, and timeouts. |
| Read request context | HttpRequestCapturer, HttpRequestHolder | The current request exists only inside Reactor Context. |
| Stream buffers | readAsDataBuffer, write, join, release | Distinguish cold flows, byte limits, and pooled-buffer release. |
| Return API errors | ApiExceptionHandler, ApiErrorBody | Handles a fixed exception set and exposes exception messages. |
| Observe code | observeSpring, observeSpringSuspending | The application supplies the registry and exporter. |
| Configure a dedicated WebClient | AbstractWebClientConfig | Owns event loop, SSL, timeout, codec memory, and shutdown together. |
| Create a virtual-thread executor | VirtualThreadAutoConfiguration | Requires @Import and backs off when an AsyncTaskExecutor exists. |
Learning path
Section titled “Learning path”Each chapter is grounded in the 1.11.0 source and tests. The chapters explain configuration ownership, lifecycle, and failure propagation instead of stopping at an API inventory.
- Spring Context and configuration helpers — annotation, bean, profile, and property helpers, including what is not auto-configured.
- RestClient and coroutine boundaries — blocking HTTP, nullable bodies, cancellation, and converter ownership.
- WebFlux request context and DataBuffer — Reactor Context, internal path rewriting, cold flows, and pooled-buffer lifecycle.
- Error responses and observations — status mapping, message exposure, Observation scopes, and cardinality.
- Execution resources and lifecycle — dedicated WebClient loops, coroutine scopes, and virtual-thread executors.
- Testing and ecosystem paths — focused verification and the next Spring Data, WebFlux, and observability modules.
Start with chapter 1, then jump to the capability you need. For HTTP clients, read 2 then 5. For WebFlux server code, read 3, 4, and 5.
Recommended patterns
Section titled “Recommended patterns”Let application services and configuration retain ownership of Spring objects, then import only the extensions needed at a call site. Do not let BeanFactory.findOrNull hide ambiguous beans, and use getRequiredPropertyAs when a missing value should fail startup.
Choose blocking RestClient or reactive WebClient according to the whole call path. Wrapping RestClient in a suspend function does not make it a non-blocking event-loop client. Conversely, a dedicated WebClient loop should keep thread count, timeouts, SSL trust, and shutdown in one configuration.
Integration boundaries
Section titled “Integration boundaries”Spring Boot application configuration ├── Spring Context / PropertyResolver ├── RestClient + request factory + message converters ├── WebFlux + Reactor Context + DataBuffer ├── ObservationRegistry + application exporter └── application-owned executors and lifecycle ↓ bluetape4k Spring helper APIsbluetape4k-spring-boot-core is not a general-purpose starter that creates these objects. The exceptions are the bean factory methods in AbstractWebClientConfig and an explicitly imported VirtualThreadAutoConfiguration.
Configuration
Section titled “Configuration”The module directly reads one property: bluetape4k.webclient.response-timeout for AbstractWebClientConfig.responseTimeout. Its default is the ISO-8601 duration PT30S; Spring conversion also accepts values such as 30s.
bluetape4k: webclient: response-timeout: 5sThere is no dedicated configuration-properties class or META-INF/spring/...AutoConfiguration.imports. Override threadCount, connect timeout, shutdown timeout, codec memory, and SSL context by subclassing AbstractWebClientConfig. The profile annotations are @Profile meta-annotations, not separate configuration stores.
Failure behavior
Section titled “Failure behavior”getRequiredPropertyAs propagates Spring property errors when a value is missing or cannot be converted. BeanFactory.findOrNull changes only bean absence into null; it rethrows NoUniqueBeanDefinitionException.
HTTP status and decoding errors from RestClient.retrieve() propagate unchanged. Non-null functions such as suspendGet<T> fail if the response body is absent; use suspendGetOrNull<T> when an empty body is valid.
ApiExceptionHandler covers only the declared API exceptions and HttpMessageNotReadableException. Its body omits stack traces but includes exception.message, so domain exceptions must contain messages safe for external clients.
Operations
Section titled “Operations”When using AbstractWebClientConfig, monitor the dedicated Netty loop’s thread count, connect and response timeouts, codec memory limit, and shutdown time. The default SSL context validates certificates against the JDK trust store. Never use insecureSslContext() outside development or tests.
Observation helpers start an observation, open its scope, and always stop it. Cancellation is rethrown without being recorded as an error. Keep metrics labels bounded and low-cardinality; reserve request IDs and similar values for high-cardinality trace fields.
Testing
Section titled “Testing”./gradlew :bluetape4k-spring-boot-core:test --no-configuration-cacheCustomWebClientConfigTest verifies dedicated Reactor resources and the WebClient bean. RestClientCoroutinesDslTest covers success, nullable bodies, and cancellation interrupts. HttpRequestFilterTest checks request propagation through Reactor Context, while SpringObservationSupportTest checks start/error/stop and cancellation cleanup.
ApiExceptionHandlerTest and DataBufferSupportTest cover status codes, bodies, byte limits, reads and writes, and pooled-buffer release.
Workshops and examples
Section titled “Workshops and examples”No dedicated workshop is registered in the manual manifest. The README HTTP and observation examples plus the module’s test fixtures are the runnable learning material. CustomWebClientConfig, WebClientReadmeExamplesTest, and SpringObservationSupportTest form a useful path from configuration to a call site.
For data access, continue with the Spring Data JDBC or R2DBC manuals. For lower-level coroutine and Flow rules, see bluetape4k-coroutines.
1.11.0 scope
Section titled “1.11.0 scope”This manual describes the bluetape4k-projects 1.11.0 release source. Despite the artifact name, it does not provide starter metadata, configuration-properties binding, or general application bootstrapping.
VirtualThreadAutoConfiguration is not discovered automatically. The companion executor in AbstractVirtualThreadController is shared for the process lifetime and is not closed by that class. Separate scopes in the WebFlux coroutine controller base classes do not automatically carry Reactor or Spring Security context. First check whether the request’s existing suspend context is sufficient for new code.
Source and tests
Section titled “Source and tests”- Module README
- Module build
AnnotationExtensions.ktPropertyResolverExtensions.ktRestClientCoroutinesDsl.ktAbstractWebClientConfig.ktHttpRequestCapturer.ktDataBufferSupport.ktApiExceptionHandler.ktSpringObservationSupport.ktVirtualThreadAutoConfiguration.ktCustomWebClientConfigTest.ktSpringObservationSupportTest.kt
Release diagrams
Section titled “Release diagrams”These diagrams are loaded directly from README assets published with the 1.11.0 release and pinned to its immutable commit. They describe this manual’s released structure and runtime flows, not later Snapshot changes. Select a preview to open the SVG at the same release commit.
Spring Boot Core Capability Map diagram
Section titled “Spring Boot Core Capability Map diagram”Release README: spring-boot/core/README.md
Spring WebFlux + Coroutines Request Flow diagram
Section titled “Spring WebFlux + Coroutines Request Flow diagram”Release README: spring-boot/core/README.md
RestClient Coroutines DSL Structure diagram
Section titled “RestClient Coroutines DSL Structure diagram”Release README: spring-boot/core/README.md
WebClient Dedicated Resource Configuration diagram
Section titled “WebClient Dedicated Resource Configuration diagram”Release README: spring-boot/core/README.md



