Tutorial

264 posts in this section

Pattern Matching for switch (JEP 441): Type Dispatch Without the Boilerplate

The Problem: Cascading instanceof Chains Any Java codebase handling multiple subtypes has code like this: // Java 16 and earlier — the bad old way static double calculateArea(Shape shape) { if (shape instanceof Circle) { Circle c = (Circle) shape; return Math.PI * c.radius() * c.radius(); } else if (shape instanceof Rectangle) { Rectangle r = (Rectangle) shape; return r.width() * r.height(); } else if (shape instanceof Triangle) { Triangle t = (Triangle) shape; return 0.

Continue reading »

Pausing, Resuming, and Stopping Listener Containers

Why Control Container Lifecycle? A running listener consumes from Kafka continuously. In production you need to: Pause consumption when a downstream service is overloaded (back-pressure) Resume once the downstream recovers Stop a container entirely during maintenance or feature flag toggles Restart after a configuration change without redeploying Spring Kafka exposes all of this through KafkaListenerEndpointRegistry and the container’s own lifecycle API. Container States stateDiagram-v2 [*] --> Running : start() Running --> Paused : pause() Paused --> Running : resume() Running --> Stopped : stop() Stopped --> Running : start() Paused --> Stopped : stop() Running — polling Kafka, dispatching to listener Paused — broker connection maintained, consumer heartbeat sent, no new records fetched Stopped — consumer thread terminated, partitions released back to group Paused is preferable to stopped for temporary throttling: it avoids a rebalance and keeps the consumer’s partition assignment intact.

Continue reading »

Performance Tuning: Chunk Size, Connection Pools, and Memory Management

Introduction A poorly tuned batch job can be 10–100x slower than a well-tuned one. The biggest gains come from a handful of settings — chunk size, MySQL JDBC rewrite, connection pool alignment, and avoiding unnecessary object creation. This article covers each systematically. Chunk Size — The Most Impactful Setting Chunk size determines how many items are processed per transaction. Too small = too many round trips to the database. Too large = long transactions, high memory pressure, slower rollback on failure.

Continue reading »

Primary Keys and Generated Values: IDENTITY, SEQUENCE, UUID

Introduction Primary key choice affects performance, scalability, and application design. This article covers every strategy JPA supports — from the simple AUTO_INCREMENT to UUID and composite keys — with the trade-offs of each. IDENTITY Strategy (MySQL AUTO_INCREMENT) GenerationType.IDENTITY delegates key generation to the database column’s auto-increment feature. This is the standard for MySQL. @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; Generated DDL (when ddl-auto=create): id BIGINT NOT NULL AUTO_INCREMENT How IDENTITY works with Hibernate IDENTITY has one important behaviour: Hibernate cannot batch INSERT statements when using IDENTITY.

Continue reading »

Producer @Bean Configuration: Beyond application.properties

Why @Bean Configuration? application.properties is convenient for a single producer, but insufficient when you need: Multiple producers with different serializers (e.g. one for JSON events, one for Avro) Different settings per environment built at runtime (not just property substitution) Producers sending to different clusters (e.g. primary + DR cluster) Programmatic validation of configuration at startup flowchart TB subgraph PropertiesApproach["application.properties Approach"] P1["Single producer config\nspring.kafka.producer.*\n✓ Simple\n✗ One producer only\n✗ No runtime logic"] end subgraph BeanApproach["

Continue reading »

Producer Acknowledgments: acks, min.insync.replicas, and Data Durability

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 »

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 »