What Are Acknowledgments? When a producer sends a record to a Kafka broker, it can wait for confirmation that the write was received and replicated before considering the send “complete.” The acks setting controls how much confirmation the producer requires. flowchart LR Producer["Producer"] Leader["Partition Leader\n(Broker 1)"] F1["Follower\n(Broker 2)"] F2["Follower\n(Broker 3)"] Producer -->|"ProduceRequest"| Leader Leader -->|"replicate"| F1 Leader -->|"replicate"| F2 Leader -->|"ProduceResponse ✓"| Producer style Producer fill:#3b82f6,color:#fff style Leader fill:#10b981,color:#fff The acknowledgment is the broker’s confirmation to the producer.
Continue reading »Java
223 posts in this section
Producer Retries: Backoff, Timeouts, and Retry Strategies
Why Producers Need Retries Network errors, leader elections, and broker restarts are normal events in a distributed system. Without retries, a transient broker hiccup causes permanent data loss from the producer’s perspective. With retries, the producer automatically re-sends failed records until either the broker accepts them or a timeout deadline is reached. sequenceDiagram participant Producer participant Leader as Leader (Broker 1) participant NewLeader as New Leader (Broker 2) Producer->>Leader: ProduceRequest (offset 42) Note over Leader: Broker 1 crashes mid-write Leader--xProducer: No response (timeout) Note over Producer: retry.
Continue reading »Projections and DTOs: Fetching Only What You Need
The Over-Fetching Problem By default, findAll() loads every column for every entity. A Product entity with 20 fields loads all 20 columns — even when a dropdown menu only needs id and name. This wastes bandwidth, memory, and query time. Projections let you define what shape the result should take, and Spring Data JPA generates a query that fetches only those columns. Interface Projections The simplest projection: declare an interface with getter methods matching entity field names.
Continue reading »Reactive Security with Spring WebFlux
Reactive vs. Servlet Security Spring Security’s standard configuration targets Servlet-based applications (Spring MVC). Reactive applications built with Spring WebFlux run on a non-blocking event loop — there is no thread-per-request model, so ThreadLocal-based SecurityContextHolder does not work. Spring Security provides a parallel reactive stack: Servlet Reactive SecurityFilterChain SecurityWebFilterChain HttpSecurity ServerHttpSecurity SecurityContextHolder ReactiveSecurityContextHolder UserDetailsService ReactiveUserDetailsService AuthenticationManager ReactiveAuthenticationManager @EnableWebSecurity @EnableWebFluxSecurity @EnableMethodSecurity @EnableReactiveMethodSecurity Dependencies <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> Spring Security auto-configures reactive security when WebFlux is on the classpath.
Continue reading »Record Patterns (JEP 440): Destructuring Records with Power and Precision
Records Recap Records (Java 16, JEP 395) are transparent carriers of immutable data: record Point(int x, int y) {} record ColoredPoint(Point point, String color) {} record Line(Point start, Point end) {} The compiler generates a constructor, accessor methods (x(), y()), equals, hashCode, and toString. Before Java 21, accessing record components required calling accessor methods: Object obj = new ColoredPoint(new Point(3, 4), "red"); if (obj instanceof ColoredPoint cp) { int x = cp.
Continue reading »Records (JEP 395): Immutable Data Classes Without the Boilerplate
Finalized in Java 16 (JEP 395). Available in all Java 16+ releases, including Java 17. Previous previews: Java 14 (JEP 359) and Java 15 (JEP 384). The Problem: Data Classes in Java Writing a simple immutable data class in Java 11 requires significant boilerplate: public final class Point { private final int x; private final int y; public Point(int x, int y) { this.x = x; this.y = y; } public int x() { return x; } public int y() { return y; } @Override public boolean equals(Object o) { if (this == o) return true; if (!
Continue reading »Refresh Tokens and Token Rotation
Why Refresh Tokens? Short-lived access tokens (15–60 minutes) limit the damage if a token is stolen — it expires quickly. But forcing users to log in every hour is terrible UX. Refresh tokens solve this: a long-lived token (7–30 days) stored securely lets the client silently obtain a new access token when the old one expires. The user stays logged in indefinitely without re-entering credentials. sequenceDiagram participant Client participant AuthServer as Auth Endpoint participant API as Protected API Client->>AuthServer: POST /api/auth/login AuthServer-->>Client: {accessToken: exp 15min, refreshToken: exp 7d} Note over Client,API: Normal API usage (15 min) Client->>API: GET /api/data\nAuthorization: Bearer {accessToken} API-->>Client: 200 OK Note over Client,API: Access token expires Client->>API: GET /api/data\nAuthorization: Bearer {expiredToken} API-->>Client: 401 Unauthorized Note over Client,API: Silent token refresh Client->>AuthServer: POST /api/auth/refresh\n{refreshToken} AuthServer-->>Client: {newAccessToken, newRefreshToken} Client->>API: GET /api/data\nAuthorization: Bearer {newAccessToken} API-->>Client: 200 OK Token Rotation: Every Refresh Issues a New Refresh Token Token rotation is the critical security mechanism: every time a refresh token is used, the server issues a new refresh token and invalidates the old one.
Continue reading »Remote Partitioning and Remote Chunking with Kafka
Introduction Local partitioning (Article 21) runs all workers on one JVM. When a single machine is the bottleneck — CPU, memory, or network bandwidth — you need workers on separate machines. Spring Batch Integration provides two patterns for this: Pattern What distributes Coordinator controls Workers do Remote Partitioning Partition descriptors (small messages) Data splitting, aggregation Full read-process-write per partition Remote Chunking Actual items (larger messages) Reading Processing + writing only Remote partitioning is the more common choice — workers read directly from the database/file, so only small partition metadata crosses the network.
Continue reading »Removed and Deprecated APIs: Java EE, JavaFX, Nashorn (JEP 320, 335, 336)
Removal Timeline API Deprecated In Removed In JEP Java EE modules (JAXB, JAX-WS, etc.) Java 9 Java 11 JEP 320 JavaFX Bundled with Java 9 Unbundled in Java 11 — Nashorn JavaScript Engine Java 11 Java 15 JEP 335 Pack200 tools and API Java 11 Java 14 JEP 336 javah tool Java 9 Java 10 JEP 313 sun.misc.BASE64Encoder/Decoder Java 8 Java 11 Encapsulation Thread.destroy(), Thread.stop(Throwable) Old Java 11 — Applet API Java 9 Java 17 JEP 289 Java EE Modules Removed (JEP 320) The six Java EE modules that shipped with Java SE 6–10 were removed from Java 11.
Continue reading »Repository Interfaces: CrudRepository, JpaRepository, and How They Work
Introduction Spring Data JPA’s repository abstraction eliminates the DAO boilerplate that every Java application used to require. You declare an interface, extend one of the repository base interfaces, and Spring generates a complete implementation at startup — find, save, delete, count, and more — with zero code written. The Repository Hierarchy Repository<T, ID> ← Marker interface — no methods │ └── CrudRepository<T, ID> ← Basic CRUD: save, find, delete, count │ └── PagingAndSortingRepository<T, ID> ← + findAll(Pageable), findAll(Sort) │ └── JpaRepository<T, ID> ← + flush, saveAndFlush, deleteInBatch Each interface adds more operations.
Continue reading »