The Problem Kafka Solves Imagine an e-commerce platform. A customer places an order. What needs to happen next? Inventory must be reserved Payment must be charged A confirmation email must be sent The warehouse must be notified to pick and pack Analytics must record the sale Fraud detection must evaluate the transaction One request. Six downstream systems. In a traditional REST architecture, the Order Service calls each of those six services directly — synchronously, one after another.
Continue reading »Tutorial
264 posts in this section
X.509 Certificate Authentication
What Is X.509 Authentication? X.509 authentication (also called mutual TLS or mTLS) uses digital certificates instead of passwords. The client presents a certificate during the TLS handshake. The server verifies the certificate against a trusted Certificate Authority (CA) and extracts the user identity from the certificate’s Common Name (CN) or Subject Alternative Name (SAN). sequenceDiagram participant Client as Client (with certificate) participant Server as Spring Boot Server Client->>Server: TLS ClientHello Server->>Client: TLS ServerHello + Server Certificate Server->>Client: CertificateRequest (ask for client cert) Client->>Server: Client Certificate + CertificateVerify Server->>Server: Verify against trusted CA Server->>Server: Extract CN from certificate: "
Continue reading »Adopting Liquibase on an Existing Production Database
Most teams don’t start with Liquibase. You inherit a production database that’s been running for years, modified by scripts, hotfixes, and well-intentioned developers who “just ran it manually.” Now you want version control. You want repeatable deployments. You want to stop the “did you run the migration?” Slack message. The good news: you can adopt Liquibase without touching production data. The bad news: it requires care — not complexity, just care.
Continue reading »Advanced Processing: CompositeItemProcessor, External APIs, and Async Processing
Introduction Real batch jobs often need more than one transformation step per item. You might validate first, then normalize, then enrich, then convert to the output type. CompositeItemProcessor chains multiple single-responsibility processors together. For I/O-bound enrichment steps, AsyncItemProcessor runs processing concurrently on a thread pool — giving you parallelism without rewriting your step as multi-threaded. CompositeItemProcessor CompositeItemProcessor chains a list of processors. The output of each processor becomes the input to the next.
Continue reading »Advanced Writers: JpaItemWriter, CompositeItemWriter, and Custom Writers
Introduction The previous article covered the two most common writers: FlatFileItemWriter for files and JdbcBatchItemWriter for database inserts. This article covers advanced scenarios: Persisting JPA entities with JpaItemWriter Writing to multiple destinations simultaneously with CompositeItemWriter Routing items to different writers based on content with ClassifierCompositeItemWriter Building custom writers for REST APIs, message queues, and cloud storage Combining a writer with a post-step cleanup tasklet JpaItemWriter JpaItemWriter calls EntityManager.merge() on each item.
Continue reading »API Documentation with OpenAPI and Springdoc
Good API documentation is non-negotiable. Springdoc reads your Spring MVC code and auto-generates interactive OpenAPI 3.1 documentation — no separate doc files to maintain. Setup <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>2.5.0</version> </dependency> Start the app and visit: Swagger UI: http://localhost:8080/swagger-ui.html OpenAPI JSON: http://localhost:8080/v3/api-docs OpenAPI YAML: http://localhost:8080/v3/api-docs.yaml Springdoc scans your @RestController classes and generates the spec automatically. Zero configuration needed for basic docs. Configuring the API Info @Configuration public class OpenApiConfig { @Bean public OpenAPI openAPI() { return new OpenAPI() .
Continue reading »API Gateway with Spring Cloud Gateway
The API gateway is the single entry point for all client traffic. It handles routing to downstream services, authentication, rate limiting, and request/response transformation — so individual services don’t have to. Setup <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> Spring Cloud Gateway is reactive (WebFlux-based) — don’t include spring-boot-starter-web. Route Configuration YAML Configuration spring: application: name: api-gateway cloud: gateway: routes: - id: order-service uri: lb://order-service # lb:// = load-balanced via Eureka predicates: - Path=/api/orders/** filters: - StripPrefix=0 # don't strip path prefix - AddRequestHeader=X-Gateway-Source, api-gateway - id: customer-service uri: lb://customer-service predicates: - Path=/api/customers/** filters: - StripPrefix=0 - id: payment-service uri: lb://payment-service predicates: - Path=/api/payments/** filters: - StripPrefix=0 # Versioned routing - id: order-service-v2 uri: lb://order-service-v2 predicates: - Path=/api/v2/orders/** - Header=X-API-Version, 2 default-filters: - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin Programmatic Route Configuration @Configuration public class GatewayRouteConfig { @Bean public RouteLocator routeLocator(RouteLocatorBuilder builder) { return builder.
Continue reading »API Versioning in Spring Boot 4
APIs evolve. Adding fields is safe — removing or changing fields breaks clients. Versioning gives you a path to evolve the API without breaking existing integrations. When You Need Versioning You need a new API version when: Removing a field from a response Changing a field’s type or semantics Changing URL structure significantly Breaking backward-incompatible business logic changes You don’t need a new version for: Adding new optional fields (non-breaking) Adding new endpoints Bug fixes that don’t change the contract Strategy 1: URL Path Versioning The most common and explicit approach:
Continue reading »Application Configuration: Properties, YAML, and Profiles
Every real application needs different configuration for different environments — a local database for dev, a connection pool for staging, a secret manager for prod. This article covers everything Spring Boot gives you to handle this cleanly. application.properties vs application.yml Spring Boot reads configuration from src/main/resources/application.properties (or .yml) by default. Both formats express the same thing: application.properties: server.port=8080 spring.datasource.url=jdbc:postgresql://localhost:5432/orders spring.datasource.username=app spring.datasource.password=secret spring.jpa.show-sql=false application.yml: server: port: 8080 spring: datasource: url: jdbc:postgresql://localhost:5432/orders username: app password: secret jpa: show-sql: false YAML is generally preferred for nested properties — it’s less repetitive.
Continue reading »Async Processing with @Async and Virtual Threads
Not every operation needs to complete before the response returns. Sending an email, generating a report, publishing an event — these can run in the background. Async processing keeps request latency low while the work continues. @Async — Fire and Forget @SpringBootApplication @EnableAsync public class OrderServiceApplication { } @Service @Slf4j public class NotificationService { @Async // runs in a separate thread public void sendOrderConfirmation(Order order) { log.info("Sending confirmation for order {}", order.
Continue reading »