spring-boot4-skill 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,304 @@
1
+ # Build Templates — Spring Boot 4 / Spring Framework 7 (2026)
2
+
3
+ ---
4
+
5
+ ## Table of Contents
6
+ 1. [Gradle KTS — Full Application Template](#1-gradle-kts--full-application-template)
7
+ 2. [Maven POM — Full Application Template](#2-maven-pom--full-application-template)
8
+ 3. [Key BOM Versions (2026)](#3-key-bom-versions-2026)
9
+ 4. [Spring Initializr CLI Quick Start](#4-spring-initializr-cli-quick-start)
10
+
11
+ ---
12
+
13
+ ## 1. Gradle KTS — Full Application Template
14
+
15
+ ```kotlin
16
+ // build.gradle.kts
17
+ import org.springframework.boot.gradle.tasks.bundling.BootJar
18
+
19
+ plugins {
20
+ java
21
+ id("org.springframework.boot") version "4.0.3"
22
+ id("io.spring.dependency-management") version "1.1.7"
23
+ id("org.graalvm.buildtools.native") version "0.10.4" // optional: native image
24
+ }
25
+
26
+ group = "com.example"
27
+ version = "0.0.1-SNAPSHOT"
28
+
29
+ java {
30
+ toolchain {
31
+ languageVersion = JavaLanguageVersion.of(25)
32
+ }
33
+ }
34
+
35
+ // Enable preview features (Structured Concurrency, Scoped Values GA in Java 25)
36
+ tasks.withType<JavaCompile> {
37
+ options.compilerArgs.addAll(listOf("--enable-preview"))
38
+ }
39
+
40
+ tasks.withType<Test> {
41
+ jvmArgs("--enable-preview")
42
+ useJUnitPlatform()
43
+ }
44
+
45
+ tasks.named<BootJar>("bootJar") {
46
+ jvmArguments.addAll(listOf("--enable-preview"))
47
+ }
48
+
49
+ repositories {
50
+ mavenCentral()
51
+ }
52
+
53
+ dependencyManagement {
54
+ imports {
55
+ mavenBom("org.springframework.modulith:spring-modulith-bom:2.0.3")
56
+ }
57
+ }
58
+
59
+ dependencies {
60
+ // --- Web ---
61
+ implementation("org.springframework.boot:spring-boot-starter-web")
62
+ // implementation("org.springframework.boot:spring-boot-starter-webflux") // reactive
63
+
64
+ // --- Data ---
65
+ implementation("org.springframework.boot:spring-boot-starter-data-jpa")
66
+ implementation("org.springframework.boot:spring-boot-starter-jdbc")
67
+ runtimeOnly("org.postgresql:postgresql")
68
+ // runtimeOnly("com.h2database:h2") // dev/test
69
+
70
+ // --- Validation ---
71
+ implementation("org.springframework.boot:spring-boot-starter-validation")
72
+
73
+ // --- Security ---
74
+ implementation("org.springframework.boot:spring-boot-starter-security")
75
+ implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server")
76
+
77
+ // --- Observability ---
78
+ implementation("org.springframework.boot:spring-boot-starter-actuator")
79
+ implementation("io.micrometer:micrometer-tracing-bridge-otel")
80
+ implementation("io.opentelemetry:opentelemetry-exporter-otlp")
81
+ runtimeOnly("io.micrometer:micrometer-registry-prometheus")
82
+
83
+ // --- Null Safety ---
84
+ implementation("org.jspecify:jspecify:1.0.0")
85
+
86
+ // --- Spring Modulith (optional) ---
87
+ implementation("org.springframework.modulith:spring-modulith-starter-core")
88
+ implementation("org.springframework.modulith:spring-modulith-starter-jpa")
89
+
90
+ // --- Dev Tools ---
91
+ developmentOnly("org.springframework.boot:spring-boot-devtools")
92
+ annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
93
+
94
+ // --- Testing ---
95
+ testImplementation("org.springframework.boot:spring-boot-starter-test")
96
+ testImplementation("org.springframework.security:spring-security-test")
97
+ testImplementation("org.springframework.modulith:spring-modulith-starter-test")
98
+ testImplementation("org.testcontainers:postgresql")
99
+ testImplementation("org.testcontainers:junit-jupiter")
100
+ }
101
+ ```
102
+
103
+ ---
104
+
105
+ ## 2. Maven POM — Full Application Template
106
+
107
+ ```xml
108
+ <?xml version="1.0" encoding="UTF-8"?>
109
+ <project xmlns="http://maven.apache.org/POM/4.0.0"
110
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
111
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
112
+ https://maven.apache.org/xsd/maven-4.0.0.xsd">
113
+ <modelVersion>4.0.0</modelVersion>
114
+
115
+ <parent>
116
+ <groupId>org.springframework.boot</groupId>
117
+ <artifactId>spring-boot-starter-parent</artifactId>
118
+ <version>4.0.3</version>
119
+ <relativePath/>
120
+ </parent>
121
+
122
+ <groupId>com.example</groupId>
123
+ <artifactId>my-app</artifactId>
124
+ <version>0.0.1-SNAPSHOT</version>
125
+ <packaging>jar</packaging>
126
+
127
+ <properties>
128
+ <java.version>25</java.version>
129
+ <spring-modulith.version>2.0.3</spring-modulith.version>
130
+ <jspecify.version>1.0.0</jspecify.version>
131
+ </properties>
132
+
133
+ <dependencyManagement>
134
+ <dependencies>
135
+ <dependency>
136
+ <groupId>org.springframework.modulith</groupId>
137
+ <artifactId>spring-modulith-bom</artifactId>
138
+ <version>${spring-modulith.version}</version>
139
+ <scope>import</scope>
140
+ <type>pom</type>
141
+ </dependency>
142
+ </dependencies>
143
+ </dependencyManagement>
144
+
145
+ <dependencies>
146
+ <!-- Web -->
147
+ <dependency>
148
+ <groupId>org.springframework.boot</groupId>
149
+ <artifactId>spring-boot-starter-web</artifactId>
150
+ </dependency>
151
+
152
+ <!-- Data -->
153
+ <dependency>
154
+ <groupId>org.springframework.boot</groupId>
155
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
156
+ </dependency>
157
+ <dependency>
158
+ <groupId>org.postgresql</groupId>
159
+ <artifactId>postgresql</artifactId>
160
+ <scope>runtime</scope>
161
+ </dependency>
162
+
163
+ <!-- Validation -->
164
+ <dependency>
165
+ <groupId>org.springframework.boot</groupId>
166
+ <artifactId>spring-boot-starter-validation</artifactId>
167
+ </dependency>
168
+
169
+ <!-- Security -->
170
+ <dependency>
171
+ <groupId>org.springframework.boot</groupId>
172
+ <artifactId>spring-boot-starter-security</artifactId>
173
+ </dependency>
174
+ <dependency>
175
+ <groupId>org.springframework.boot</groupId>
176
+ <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
177
+ </dependency>
178
+
179
+ <!-- Observability -->
180
+ <dependency>
181
+ <groupId>org.springframework.boot</groupId>
182
+ <artifactId>spring-boot-starter-actuator</artifactId>
183
+ </dependency>
184
+ <dependency>
185
+ <groupId>io.micrometer</groupId>
186
+ <artifactId>micrometer-tracing-bridge-otel</artifactId>
187
+ </dependency>
188
+ <dependency>
189
+ <groupId>io.opentelemetry</groupId>
190
+ <artifactId>opentelemetry-exporter-otlp</artifactId>
191
+ </dependency>
192
+
193
+ <!-- Null Safety -->
194
+ <dependency>
195
+ <groupId>org.jspecify</groupId>
196
+ <artifactId>jspecify</artifactId>
197
+ <version>${jspecify.version}</version>
198
+ </dependency>
199
+
200
+ <!-- Spring Modulith -->
201
+ <dependency>
202
+ <groupId>org.springframework.modulith</groupId>
203
+ <artifactId>spring-modulith-starter-core</artifactId>
204
+ </dependency>
205
+
206
+ <!-- Testing -->
207
+ <dependency>
208
+ <groupId>org.springframework.boot</groupId>
209
+ <artifactId>spring-boot-starter-test</artifactId>
210
+ <scope>test</scope>
211
+ </dependency>
212
+ <dependency>
213
+ <groupId>org.springframework.modulith</groupId>
214
+ <artifactId>spring-modulith-starter-test</artifactId>
215
+ <scope>test</scope>
216
+ </dependency>
217
+ <dependency>
218
+ <groupId>org.testcontainers</groupId>
219
+ <artifactId>postgresql</artifactId>
220
+ <scope>test</scope>
221
+ </dependency>
222
+ </dependencies>
223
+
224
+ <build>
225
+ <plugins>
226
+ <plugin>
227
+ <groupId>org.springframework.boot</groupId>
228
+ <artifactId>spring-boot-maven-plugin</artifactId>
229
+ </plugin>
230
+ <plugin>
231
+ <groupId>org.apache.maven.plugins</groupId>
232
+ <artifactId>maven-compiler-plugin</artifactId>
233
+ <configuration>
234
+ <compilerArgs>
235
+ <arg>--enable-preview</arg>
236
+ </compilerArgs>
237
+ </configuration>
238
+ </plugin>
239
+ </plugins>
240
+ </build>
241
+
242
+ <!-- GraalVM Native Image (optional) -->
243
+ <profiles>
244
+ <profile>
245
+ <id>native</id>
246
+ <build>
247
+ <plugins>
248
+ <plugin>
249
+ <groupId>org.graalvm.buildtools</groupId>
250
+ <artifactId>native-maven-plugin</artifactId>
251
+ </plugin>
252
+ </plugins>
253
+ </build>
254
+ </profile>
255
+ </profiles>
256
+ </project>
257
+ ```
258
+
259
+ ---
260
+
261
+ ## 3. Key BOM Versions (2026)
262
+
263
+ | Library | Version |
264
+ |---|---|
265
+ | Spring Boot | 4.0.3 |
266
+ | Spring Framework | 7.0.5 |
267
+ | Spring Modulith | 2.0.3 |
268
+ | Spring Security | 7.x (managed by Boot) |
269
+ | Spring Data | 4.x (managed by Boot) |
270
+ | Hibernate ORM | 7.0 |
271
+ | JSpecify | 1.0.0 |
272
+ | Jackson | 3.x |
273
+ | GraalVM Build Tools | 0.10.4 |
274
+ | Testcontainers | 1.21.x |
275
+ | JUnit 5 | 5.12.x |
276
+ | Micrometer | 1.15.x |
277
+ | io.spring.dependency-management | 1.1.7 |
278
+
279
+ ---
280
+
281
+ ## 4. Spring Initializr CLI Quick Start
282
+
283
+ ```bash
284
+ # Using Spring CLI (spring init)
285
+ spring init \
286
+ --boot-version=4.0.3 \
287
+ --java-version=25 \
288
+ --build=gradle-project-kotlin \
289
+ --dependencies=web,data-jpa,postgresql,security,actuator,validation,devtools \
290
+ --group-id=com.example \
291
+ --artifact-id=my-service \
292
+ --name=MyService \
293
+ my-service
294
+
295
+ # Or via curl to start.spring.io
296
+ curl https://start.spring.io/starter.tgz \
297
+ -d type=gradle-project-kotlin \
298
+ -d bootVersion=4.0.3 \
299
+ -d javaVersion=25 \
300
+ -d dependencies=web,data-jpa,postgresql,security,actuator,validation \
301
+ -d groupId=com.example \
302
+ -d artifactId=my-service \
303
+ | tar -xzvf -
304
+ ```
@@ -0,0 +1,347 @@
1
+ # Spring Boot 4.0.x — Feature Reference
2
+
3
+ **Version**: 4.0.3 (Stable) | **Framework**: Spring 7.0.x | **Java baseline**: 17 (25 recommended)
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+ 1. [Platform Requirements](#1-platform-requirements)
9
+ 2. [Auto-Configuration Changes](#2-auto-configuration-changes)
10
+ 3. [Testing — @SpringBootTest & Slices](#3-testing--springboottest--slices)
11
+ 4. [Actuator & Observability](#4-actuator--observability)
12
+ 5. [GraalVM Native Image](#5-graalvm-native-image)
13
+ 6. [Virtual Threads (Project Loom)](#6-virtual-threads-project-loom)
14
+ 7. [Structured Concurrency (Java 25)](#7-structured-concurrency-java-25)
15
+ 8. [Scoped Values (Java 25)](#8-scoped-values-java-25)
16
+ 9. [Docker Compose Support](#9-docker-compose-support)
17
+ 10. [Spring Security 7 Basics](#10-spring-security-7-basics)
18
+
19
+ ---
20
+
21
+ ## 1. Platform Requirements
22
+
23
+ | Component | Version |
24
+ |---|---|
25
+ | Java (minimum) | 17 |
26
+ | Java (recommended) | 25 |
27
+ | GraalVM | 24+ |
28
+ | Spring Framework | 7.0.x |
29
+ | Jakarta EE | 11 |
30
+ | Servlet | 6.1 |
31
+ | JPA (Hibernate ORM) | 3.2 / 7.0 |
32
+ | Bean Validation | 3.1 |
33
+ | Jackson | 3.x |
34
+ | Kotlin | 2.2 |
35
+
36
+ ---
37
+
38
+ ## 2. Auto-Configuration Changes
39
+
40
+ ### Functional Bean Registration (Native-Friendly)
41
+
42
+ Avoid `@ComponentScan` when targeting GraalVM. Use functional registration in `ApplicationContext` initialization:
43
+
44
+ ```java
45
+ @SpringBootApplication(proxyBeanMethods = false)
46
+ public class Application {
47
+
48
+ public static void main(String[] args) {
49
+ new SpringApplicationBuilder(Application.class)
50
+ .initializers(ctx -> {
51
+ ctx.registerBean(UserService.class, UserServiceImpl::new);
52
+ ctx.registerBean(UserRepository.class, UserRepositoryImpl::new);
53
+ })
54
+ .run(args);
55
+ }
56
+ }
57
+ ```
58
+
59
+ ### Condition-Based Auto-Configuration
60
+
61
+ ```java
62
+ @AutoConfiguration
63
+ @ConditionalOnClass(DataSource.class)
64
+ @ConditionalOnMissingBean(JdbcClient.class)
65
+ public class JdbcClientAutoConfiguration {
66
+
67
+ @Bean
68
+ JdbcClient jdbcClient(DataSource dataSource) {
69
+ return JdbcClient.create(dataSource);
70
+ }
71
+ }
72
+ ```
73
+
74
+ ---
75
+
76
+ ## 3. Testing — @SpringBootTest & Slices
77
+
78
+ ### Full Context Test
79
+
80
+ ```java
81
+ @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
82
+ class ApplicationIntegrationTest {
83
+
84
+ @Autowired RestTestClient client;
85
+
86
+ @Test
87
+ void healthEndpointIsUp() {
88
+ client.get().uri("/actuator/health")
89
+ .exchange().expectStatus().isOk();
90
+ }
91
+ }
92
+ ```
93
+
94
+ ### Web Layer Slice
95
+
96
+ ```java
97
+ @WebMvcTest(ProductController.class)
98
+ class ProductControllerTest {
99
+
100
+ @Autowired MockMvc mvc;
101
+ @MockitoBean ProductService productService;
102
+
103
+ @Test
104
+ void shouldReturn200() throws Exception {
105
+ given(productService.findAll()).willReturn(List.of(new Product(1L, "Widget")));
106
+ mvc.perform(get("/api/products"))
107
+ .andExpect(status().isOk())
108
+ .andExpect(jsonPath("$[0].name").value("Widget"));
109
+ }
110
+ }
111
+ ```
112
+
113
+ ### Data Layer Slice
114
+
115
+ ```java
116
+ @DataJpaTest
117
+ class UserRepositoryTest {
118
+
119
+ @Autowired UserRepository repository;
120
+
121
+ @Test
122
+ void shouldPersistUser() {
123
+ User saved = repository.save(new User("Alice", "alice@example.com"));
124
+ assertThat(saved.id()).isNotNull();
125
+ }
126
+ }
127
+ ```
128
+
129
+ ---
130
+
131
+ ## 4. Actuator & Observability
132
+
133
+ Spring Boot 4 ships first-class **Micrometer Tracing + OpenTelemetry** support.
134
+
135
+ ```yaml
136
+ # application.yaml
137
+ management:
138
+ endpoints:
139
+ web:
140
+ exposure:
141
+ include: health,info,metrics,prometheus,traces
142
+ tracing:
143
+ sampling:
144
+ probability: 1.0
145
+ otlp:
146
+ metrics:
147
+ export:
148
+ url: http://otel-collector:4318/v1/metrics
149
+ tracing:
150
+ endpoint: http://otel-collector:4318/v1/traces
151
+ ```
152
+
153
+ ```kotlin
154
+ // build.gradle.kts
155
+ implementation("io.micrometer:micrometer-tracing-bridge-otel")
156
+ implementation("io.opentelemetry:opentelemetry-exporter-otlp")
157
+ ```
158
+
159
+ Custom span:
160
+
161
+ ```java
162
+ @Service
163
+ public class OrderService {
164
+
165
+ private final Tracer tracer;
166
+
167
+ @Observed(name = "order.process", contextualName = "Processing order")
168
+ public Order process(OrderRequest request) {
169
+ Span span = tracer.nextSpan().name("validate").start();
170
+ try (Tracer.SpanInScope ws = tracer.withSpan(span)) {
171
+ validate(request);
172
+ } finally {
173
+ span.end();
174
+ }
175
+ return persist(request);
176
+ }
177
+ }
178
+ ```
179
+
180
+ ---
181
+
182
+ ## 5. GraalVM Native Image
183
+
184
+ ```kotlin
185
+ // build.gradle.kts
186
+ plugins {
187
+ id("org.graalvm.buildtools.native") version "0.10.4"
188
+ }
189
+
190
+ graalvmNative {
191
+ binaries {
192
+ named("main") {
193
+ imageName.set("app")
194
+ buildArgs.add("--enable-preview")
195
+ }
196
+ }
197
+ }
198
+ ```
199
+
200
+ Build native image:
201
+
202
+ ```bash
203
+ ./gradlew nativeCompile
204
+ ./build/native/nativeCompile/app
205
+ ```
206
+
207
+ **AOT hints** when reflection is unavoidable:
208
+
209
+ ```java
210
+ @RegisterReflectionForBinding(MyDto.class)
211
+ @Configuration(proxyBeanMethods = false)
212
+ public class NativeHintsConfig {}
213
+ ```
214
+
215
+ ---
216
+
217
+ ## 6. Virtual Threads (Project Loom)
218
+
219
+ Enable via single property — no code changes needed for existing Spring MVC apps:
220
+
221
+ ```yaml
222
+ # application.yaml
223
+ spring:
224
+ threads:
225
+ virtual:
226
+ enabled: true
227
+ ```
228
+
229
+ Programmatic usage:
230
+
231
+ ```java
232
+ try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
233
+ executor.submit(() -> callExternalService());
234
+ }
235
+ ```
236
+
237
+ ---
238
+
239
+ ## 7. Structured Concurrency (Java 25)
240
+
241
+ Use `StructuredTaskScope` for fan-out patterns with lifecycle guarantees.
242
+
243
+ ```java
244
+ import java.util.concurrent.StructuredTaskScope;
245
+
246
+ @Service
247
+ public class DashboardService {
248
+
249
+ public Dashboard loadDashboard(String userId) throws Exception {
250
+ try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
251
+
252
+ var orders = scope.fork(() -> orderService.findByUser(userId));
253
+ var profile = scope.fork(() -> profileService.find(userId));
254
+ var payments = scope.fork(() -> paymentService.findByUser(userId));
255
+
256
+ scope.join().throwIfFailed();
257
+
258
+ return new Dashboard(profile.get(), orders.get(), payments.get());
259
+ }
260
+ }
261
+ }
262
+ ```
263
+
264
+ ---
265
+
266
+ ## 8. Scoped Values (Java 25)
267
+
268
+ `ScopedValue` replaces `ThreadLocal` for context propagation in virtual threads.
269
+
270
+ ```java
271
+ public final class RequestContext {
272
+ public static final ScopedValue<String> TENANT_ID = ScopedValue.newInstance();
273
+ public static final ScopedValue<User> CURRENT_USER = ScopedValue.newInstance();
274
+ }
275
+
276
+ // Set in a filter
277
+ ScopedValue.where(RequestContext.TENANT_ID, tenantId)
278
+ .where(RequestContext.CURRENT_USER, user)
279
+ .run(() -> filterChain.doFilter(request, response));
280
+
281
+ // Read anywhere in the call stack
282
+ String tenant = RequestContext.TENANT_ID.get();
283
+ ```
284
+
285
+ ---
286
+
287
+ ## 9. Docker Compose Support
288
+
289
+ Spring Boot 4 auto-detects `compose.yaml` and starts services before the application.
290
+
291
+ ```yaml
292
+ # compose.yaml
293
+ services:
294
+ postgres:
295
+ image: postgres:17
296
+ environment:
297
+ POSTGRES_DB: appdb
298
+ POSTGRES_USER: app
299
+ POSTGRES_PASSWORD: secret
300
+ ports: ["5432:5432"]
301
+ redis:
302
+ image: redis:8
303
+ ports: ["6379:6379"]
304
+ ```
305
+
306
+ ```yaml
307
+ # application.yaml
308
+ spring:
309
+ docker:
310
+ compose:
311
+ enabled: true
312
+ lifecycle-management: start-and-stop
313
+ ```
314
+
315
+ No manual connection properties needed — Boot auto-configures `DataSource` and `RedisTemplate`.
316
+
317
+ ---
318
+
319
+ ## 10. Spring Security 7 Basics
320
+
321
+ Lambda DSL is the only supported style in Spring Security 7.
322
+
323
+ ```java
324
+ @Configuration
325
+ @EnableWebSecurity
326
+ public class SecurityConfig {
327
+
328
+ @Bean
329
+ SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
330
+ return http
331
+ .authorizeHttpRequests(auth -> auth
332
+ .requestMatchers("/api/public/**").permitAll()
333
+ .requestMatchers("/api/admin/**").hasRole("ADMIN")
334
+ .anyRequest().authenticated())
335
+ .oauth2ResourceServer(oauth2 -> oauth2
336
+ .jwt(jwt -> jwt.decoder(jwtDecoder())))
337
+ .sessionManagement(session -> session
338
+ .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
339
+ .build();
340
+ }
341
+
342
+ @Bean
343
+ JwtDecoder jwtDecoder() {
344
+ return NimbusJwtDecoder.withJwkSetUri("https://auth.example.com/.well-known/jwks.json").build();
345
+ }
346
+ }
347
+ ```