# Spring Boot 3.4: Semua fitur baru dijelaskan lengkap > Spring Boot 3.4 menghadirkan structured logging native, virtual threads yang diperluas, graceful shutdown default, dan MockMvcTester. Panduan lengkap fitur-fitur baru. - Published: 2026-01-16 - Updated: 2026-04-10 - Author: SharpSkill - Tags: spring boot, java, spring boot 3.4, spring framework, backend - Reading time: 12 min --- Spring Boot 3.4, dirilis pada November 2024, menghadirkan peningkatan signifikan untuk produktivitas developer dan performa aplikasi. Versi ini memperkenalkan structured logging native, mengaktifkan graceful shutdown secara default, dan memperluas dukungan virtual threads di seluruh framework. > **Prasyarat** > > Spring Boot 3.4 memerlukan minimal Java 17 dan mendukung Java 21 untuk virtual threads. Versi ini menggunakan Spring Framework 6.2. ## Structured logging native Structured logging merupakan kemajuan penting untuk observabilitas aplikasi. Alih-alih log berbasis teks yang sulit dianalisis, Spring Boot 3.4 menghasilkan log dalam format JSON yang dapat dikonsumsi oleh tools seperti Elasticsearch, Grafana Loki, atau Datadog. Tiga format didukung secara native: Elastic Common Schema (ECS), Logstash, dan Graylog Extended Log Format (GELF). ```properties # application.properties # Enable structured logging in console logging.structured.format.console=ecs # Or for log files logging.structured.format.file=logstash ``` Konfigurasi sederhana ini secara otomatis menghasilkan log JSON terstruktur yang terformat. ```java // LoggingController.java @RestController @RequestMapping("/api/demo") public class LoggingController { // Logger injection via SLF4J private static final Logger logger = LoggerFactory.getLogger(LoggingController.class); @GetMapping("/action") public ResponseEntity performAction(@RequestParam String userId) { // Log will be automatically formatted as structured JSON logger.info("Action performed by user: {}", userId); return ResponseEntity.ok("Action completed"); } } ``` Dengan format ECS diaktifkan, log ini menjadi objek JSON yang berisi timestamp, level, pesan, nama kelas, thread, dan metadata aplikasi. Struktur ini menyederhanakan pencarian dan agregasi di platform monitoring. ## Graceful Shutdown aktif secara default Perubahan penting: graceful shutdown kini aktif secara default. Request HTTP yang sedang berjalan diproses sebelum server dimatikan, mencegah error 502 selama deployment. ```properties # application.properties # Graceful shutdown is now ON by default # To restore previous behavior (immediate shutdown): server.shutdown=immediate # Configure maximum wait timeout (30s default) spring.lifecycle.timeout-per-shutdown-phase=45s ``` Perilaku ini berlaku untuk semua embedded server: Tomcat, Jetty, Undertow, dan Reactor Netty. ```java // LifecycleConfig.java @Configuration public class LifecycleConfig { private static final Logger logger = LoggerFactory.getLogger(LifecycleConfig.class); @Bean public ApplicationListener gracefulShutdownListener() { // This listener executes at shutdown start return event -> { logger.info("Graceful shutdown initiated - completing in-flight requests"); // Custom logic: close connections, save state, etc. }; } } ``` Peningkatan ini menyederhanakan implementasi deployment tanpa downtime, tanpa perlu konfigurasi tambahan di sebagian besar kasus. ## Dukungan Virtual Threads yang diperluas Spring Boot 3.4 memperluas dukungan virtual threads (Java 21+) ke lebih banyak komponen. `OtlpMeterRegistry` dan server Undertow kini menggunakan virtual threads saat diaktifkan. ```properties # application.properties # Enable virtual threads globally spring.threads.virtual.enabled=true ``` Property tunggal ini mengubah model threading aplikasi. Setiap request HTTP mendapat virtual thread-nya sendiri, memungkinkan ribuan koneksi bersamaan tanpa menghabiskan thread pool. ```java // AsyncService.java @Service public class AsyncService { private static final Logger logger = LoggerFactory.getLogger(AsyncService.class); // With virtual threads enabled, each blocking call // no longer consumes an OS thread public String fetchExternalData() { logger.info("Executing on thread: {}", Thread.currentThread()); // Blocking HTTP call - with virtual threads, // the OS thread is released during I/O wait return restClient.get() .uri("https://api.external.com/data") .retrieve() .body(String.class); } } ``` Virtual threads unggul pada aplikasi dengan beban I/O tinggi: panggilan HTTP, query database, operasi file. Thread OS dilepaskan selama waktu tunggu dan dialokasikan ulang saat dilanjutkan. > **Kompatibilitas** > > Virtual threads memerlukan minimal Java 21. Pada Java 17, property ini diabaikan dan perilaku klasik yang berlaku. ## RestClient dan RestTemplate yang ditingkatkan Spring Boot 3.4 menormalisasi konfigurasi HTTP client. Pemilihan `HttpRequestFactory` kini mengikuti urutan prioritas yang jelas berdasarkan classpath. ```java // HttpClientConfig.java @Configuration public class HttpClientConfig { @Bean public RestClient restClient(RestClient.Builder builder) { // Spring Boot automatically chooses implementation: // 1. Apache HTTP Components (if present) // 2. Jetty Client // 3. Reactor Netty // 4. JDK HttpClient (Java 11+) // 5. SimpleClientHttpRequestFactory (fallback) return builder .baseUrl("https://api.example.com") .defaultHeader("Accept", "application/json") .build(); } } ``` Konfigurasi perilaku redirect juga disederhanakan. ```properties # application.properties # Force specific implementation spring.http.client.factory=jdk # Configure redirect behavior spring.http.client.redirects=dont-follow ``` Untuk kontrol lebih detail, `ClientHttpRequestFactoryBuilder` yang baru memungkinkan konfigurasi programatik penuh. ```java // CustomHttpClientConfig.java @Configuration public class CustomHttpClientConfig { @Bean public RestClient customRestClient(ClientHttpRequestFactoryBuilder factoryBuilder) { // Advanced factory configuration ClientHttpRequestFactory factory = factoryBuilder .httpComponents() .connectTimeout(Duration.ofSeconds(5)) .readTimeout(Duration.ofSeconds(30)) .build(); return RestClient.builder() .requestFactory(factory) .baseUrl("https://api.example.com") .build(); } } ``` Pendekatan ini menawarkan fleksibilitas maksimal dengan API yang konsisten terlepas dari implementasi HTTP yang mendasarinya. ## MockMvcTester untuk pengujian yang lebih lancar Spring Boot 3.4 memperkenalkan `MockMvcTester`, alternatif berbasis AssertJ untuk `MockMvc`. Pendekatan baru ini membuat test lebih mudah dibaca dan ekspresif. ```java // UserControllerTest.java @WebMvcTest(UserController.class) class UserControllerTest { @Autowired private MockMvcTester mockMvc; // New class! @Test void shouldReturnUserById() { // Fluent API with AssertJ mockMvc.get().uri("/api/users/{id}", 1) .assertThat() .hasStatusOk() .hasContentType(MediaType.APPLICATION_JSON) .bodyJson() .extractingPath("$.name") .isEqualTo("John Doe"); } @Test void shouldReturn404ForUnknownUser() { mockMvc.get().uri("/api/users/{id}", 999) .assertThat() .hasStatus(HttpStatus.NOT_FOUND) .bodyJson() .extractingPath("$.error") .isEqualTo("User not found"); } } ``` Dibandingkan dengan pendekatan lama menggunakan `MockMvc`, assertion lebih ringkas dan chaining terasa lebih natural. ```java // ComparisonTest.java @WebMvcTest(UserController.class) class ComparisonTest { @Autowired private MockMvcTester mockMvcTester; @Autowired private MockMvc mockMvc; @Test void withMockMvcTester() { // New approach: fluent and concise mockMvcTester.post().uri("/api/users") .contentType(MediaType.APPLICATION_JSON) .content("{\"name\": \"Jane\"}") .assertThat() .hasStatus(HttpStatus.CREATED) .hasHeader("Location", "/api/users/2"); } @Test void withClassicMockMvc() throws Exception { // Old approach: more verbose mockMvc.perform(post("/api/users") .contentType(MediaType.APPLICATION_JSON) .content("{\"name\": \"Jane\"}")) .andExpect(status().isCreated()) .andExpect(header().string("Location", "/api/users/2")); } } ``` `MockMvcTester` dikonfigurasi secara otomatis ketika AssertJ ada di classpath (sudah termasuk secara default dengan `spring-boot-starter-test`). ## Docker Compose dan Testcontainers yang ditingkatkan Dukungan Docker Compose mendapat fleksibilitas lebih dengan multiple file konfigurasi dan argumen kustom. ```properties # application.properties # Use multiple Docker Compose files spring.docker.compose.file=compose.yaml,compose-dev.yaml # Pass arguments at startup spring.docker.compose.start.arguments=--scale redis=2 # Arguments at shutdown spring.docker.compose.stop.arguments=--timeout 60 ``` Service baru secara otomatis terdeteksi dan terkonfigurasi. ```yaml # compose.yaml services: postgres: image: postgres:16 environment: POSTGRES_DB: myapp POSTGRES_USER: user POSTGRES_PASSWORD: password ports: - "5432:5432" redis-stack: image: redis/redis-stack:latest ports: - "6379:6379" - "8001:8001" # RedisInsight UI grafana-lgtm: image: grafana/otel-lgtm:latest ports: - "3000:3000" # Grafana - "4317:4317" # OTLP gRPC ``` Spring Boot 3.4 secara otomatis mendeteksi service-service ini dan mengkonfigurasi property koneksi yang sesuai. Untuk pengujian dengan Testcontainers, container baru didukung. ```java // IntegrationTestConfig.java @TestConfiguration(proxyBeanMethods = false) public class IntegrationTestConfig { @Bean @ServiceConnection public PostgreSQLContainer postgresContainer() { return new PostgreSQLContainer<>("postgres:16"); } @Bean @ServiceConnection public RedisStackContainer redisStackContainer() { // New Redis Stack support return new RedisStackContainer("redis/redis-stack:latest"); } @Bean @ServiceConnection public LgtmStackContainer observabilityContainer() { // New Grafana LGTM support (Loki, Grafana, Tempo, Mimir) return new LgtmStackContainer("grafana/otel-lgtm:latest"); } } ``` Anotasi `@ServiceConnection` secara otomatis mengkonfigurasi property koneksi, menghilangkan kebutuhan `@DynamicPropertySource` di sebagian besar kasus. ## Actuator SSL dan observabilitas Endpoint `/actuator/info` yang baru kini mengekspos informasi tentang sertifikat SSL yang dikonfigurasi: tanggal validitas, penerbit, dan subjek. ```properties # application.properties # Enable SSL information in actuator management.info.ssl.enabled=true # Configure warning threshold for expiring certificates management.health.ssl.certificate-validity-warning-threshold=30d ``` Fitur ini memungkinkan pemantauan masa berlaku sertifikat langsung melalui actuator, memudahkan otomatisasi pembaruan. ```java // SslMonitoringConfig.java @Configuration public class SslMonitoringConfig { @Bean public HealthIndicator sslCertificateHealth(SslInfo sslInfo) { return () -> { // Custom certificate validity check boolean allValid = sslInfo.getBundles().values().stream() .flatMap(bundle -> bundle.getCertificates().stream()) .allMatch(cert -> cert.getValidityEnds().isAfter(Instant.now())); return allValid ? Health.up().build() : Health.down().withDetail("reason", "Certificate expiring soon").build(); }; } } ``` Untuk observabilitas, transport OTLP kini mendukung gRPC selain HTTP. ```properties # application.properties # Use gRPC for OTLP (traces and metrics) management.otlp.tracing.transport=grpc management.otlp.tracing.endpoint=http://localhost:4317 # New: group applications together spring.application.group=payment-services ``` Grup aplikasi (`spring.application.group`) memungkinkan pengelompokan logis beberapa service di dashboard observabilitas. ## Image OCI yang lebih ringan Builder image OCI default berubah dari `paketobuildpacks/builder-jammy-base` ke `paketobuildpacks/builder-jammy-java-tiny`, menghasilkan image yang jauh lebih kecil. ```groovy // build.gradle tasks.named("bootBuildImage") { // Native ARM support (new) imagePlatform = "linux/arm64" // New security flag trustBuilder = false // Image configuration imageName = "myregistry.com/myapp:${version}" } ``` Parameter `imagePlatform` yang baru menyederhanakan build cross-platform untuk ARM dan x64. ```xml org.springframework.boot spring-boot-maven-plugin linux/arm64 paketobuildpacks/builder-jammy-java-tiny ``` Image yang dioptimalkan ini lebih cepat dimulai dan mengonsumsi lebih sedikit resource, terutama menguntungkan untuk deployment di Kubernetes. > **Catatan Migrasi** > > Perubahan builder dapat mempengaruhi aplikasi yang bergantung pada tool sistem tertentu. Uji image baru sebelum di-deploy ke production. ## Perubahan Bean Validation Spring Boot 3.4 menyelaraskan perilaku validasi dengan spesifikasi Bean Validation. Validasi tidak lagi otomatis menyebar ke property yang bersarang. ```java // ConfigProperties.java @ConfigurationProperties(prefix = "app") @Validated public class AppConfig { @NotBlank private String name; // IMPORTANT: @Valid required to cascade validation @Valid private DatabaseConfig database; // Without @Valid, ServerConfig constraints will NOT be checked private ServerConfig server; // Getters and setters } public class DatabaseConfig { @NotBlank private String url; @Min(1) private int poolSize; // Getters and setters } public class ServerConfig { @NotNull // This constraint will NOT be checked without @Valid on parent private Integer port; // Getters and setters } ``` Perubahan ini dapat mempengaruhi aplikasi yang sudah ada. Periksa kelas `@ConfigurationProperties` dan tambahkan `@Valid` di mana validasi harus menyebar. ## Deprecation @MockBean dan @SpyBean Anotasi `@MockBean` dan `@SpyBean` dari Spring Boot sudah di-deprecate demi anotasi Mockito yang baru. ```java // UserServiceTest.java (new approach) @SpringBootTest class UserServiceTest { // New: native Mockito annotations @MockitoBean private UserRepository userRepository; @MockitoSpyBean private EmailService emailService; @Autowired private UserService userService; @Test void shouldCreateUser() { // Mock configuration when(userRepository.save(any())).thenReturn(new User(1L, "test@example.com")); userService.createUser("test@example.com"); // Spy verification verify(emailService).sendWelcomeEmail("test@example.com"); } } ``` Anotasi lama masih berfungsi tetapi menampilkan peringatan deprecation. Rencanakan migrasi ke `@MockitoBean` dan `@MockitoSpyBean`. ## Kesimpulan Spring Boot 3.4 memberikan peningkatan substansial dalam produktivitas dan observabilitas: **Checklist migrasi:** - Aktifkan structured logging untuk observabilitas yang lebih baik - Verifikasi perilaku graceful shutdown (sekarang aktif secara default) - Pertimbangkan virtual threads untuk aplikasi dengan beban I/O tinggi (Java 21+) - Migrasi ke MockMvcTester untuk test yang lebih mudah dibaca - Tambahkan `@Valid` pada property `@ConfigurationProperties` yang bersarang - Ganti `@MockBean`/`@SpyBean` dengan `@MockitoBean`/`@MockitoSpyBean` - Uji image OCI baru sebelum deployment ke production Spring Boot 3.4 memperkuat posisinya sebagai framework referensi untuk pengembangan Java modern, dengan perhatian khusus pada standar observabilitas dan performa. **Sumber:** - [Spring Boot 3.4.0 Release Announcement](https://spring.io/blog/2024/11/21/spring-boot-3-4-0-available-now/) - [Spring Boot 3.4 Release Notes](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.4-Release-Notes) - [Bootiful Spring Boot 3.4](https://spring.io/blog/2024/11/24/bootiful-34-boot/) --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/id/blog/spring-boot/spring-boot-3-4-new-features