Tutorial

264 posts in this section

Dirty Checking, Flush Modes, and the First-Level Cache

The Persistence Context Revisited Article 3 introduced the persistence context — the in-memory cache of managed entities. This article goes deeper: how does the persistence context detect changes? When does it flush them to the database? And how can you tune this behaviour? Dirty Checking When you modify a managed entity, you don’t call save() or update(). You simply change the field: @Transactional public void giveDiscount(Long productId, BigDecimal discount) { Product product = productRepository.

Continue reading »

Domain Object Security: Access Control Lists (ACLs)

What ACLs Solve Role-based access control answers: “Can this user perform this action?” ACLs answer: “Can this user perform this action on this specific object?” Consider a document management system: Alice owns Document #42 — she can read and edit it Bob is a reviewer on Document #42 — he can read it but not edit Carol has no permission on Document #42 — she gets a 403 This cannot be expressed with roles alone.

Continue reading »

Dynamic Listener Containers and Programmatic Topic Registration

Why Dynamic Listeners? @KafkaListener is declared at compile time. Some scenarios require listeners created at runtime: Multi-tenant SaaS — each tenant onboards to their own topic; you can’t redeploy to add @KafkaListener for each new tenant Feature flags — enable or disable a listener without a deployment Plugin systems — modules register their own topic subscriptions when loaded Admin APIs — operators subscribe to new topics via a REST endpoint ConcurrentMessageListenerContainer The core building block is ConcurrentMessageListenerContainer — the same class @KafkaListener uses internally, but constructed and started manually:

Continue reading »

Embedded Types and Value Objects: @Embeddable and @Embedded

Introduction Not every concept in your domain deserves its own table. An Address — street, city, state, postal code — is a value object: it has no identity of its own, it belongs to an entity. JPA’s @Embeddable lets you model this as a separate Java class while storing it in the owning entity’s table. What Is an Embeddable? An @Embeddable class is a Java class whose fields are mapped to columns in the owning entity’s table — not a separate table.

Continue reading »

Enhanced Pseudo-Random Number Generators (JEP 356): A Modern PRNG API

Finalized in Java 17 (JEP 356). The Problem with Java’s Old PRNG API Java’s random number generation before Java 17 had several problems: 1. java.util.Random has poor statistical properties. The default PRNG algorithm is a 48-bit linear congruential generator (LCG). It fails many statistical tests (spectral test, birthday test). Its 2^48 period is short — exhaustible in seconds on modern hardware. 2. No common interface. java.util.Random, java.util.concurrent.ThreadLocalRandom, java.util.SplittableRandom, and java.

Continue reading »

Entity Graphs and Batch Loading: Precision Fetching

The Problem @EntityGraph Solves JOIN FETCH in @Query solves N+1 but creates inflexibility: the fetch plan is baked into the query. Two different use cases — an order detail page (needs items + customer) and an order list page (needs only customer) — require two different queries with different JOIN FETCHes. @EntityGraph separates the fetch plan from the query. You define what to load at the call site, and Spring Data JPA generates the appropriate JOIN.

Continue reading »

Entity Lifecycle States: Transient, Managed, Detached, Removed

Introduction Every JPA entity is always in one of four states. The state determines whether Hibernate is tracking the entity, whether changes are detected automatically, and what operations are valid. Understanding these states explains a large class of JPA bugs — especially the dreaded LazyInitializationException and detached entity errors. The Four States new Customer() │ │ persist / save() ▼ TRANSIENT ──────────────────────► MANAGED (not tracked) (tracked by persistence context) │ │ evict / clear / close ▼ DETACHED (no longer tracked) │ │ merge() ▼ MANAGED (re-attached) MANAGED ─── remove / delete() ──► REMOVED (delete scheduled, still in context) 1.

Continue reading »

Error Handling Basics: DefaultErrorHandler and CommonErrorHandler

What Happens When a Listener Throws? Without an error handler, an uncaught exception from @KafkaListener causes the container to log the error and retry the same record on the next poll — indefinitely. One bad record can block an entire partition forever. DefaultErrorHandler fixes this: it retries a configurable number of times with backoff, then calls a ConsumerRecordRecoverer (e.g. send to a dead-letter topic) and moves on. DefaultErrorHandler — The Modern API Spring Kafka 2.

Continue reading »

Fetch Types: EAGER vs LAZY Loading

Introduction Every relationship in JPA has a fetch type: either EAGER (load immediately with the parent) or LAZY (load only when accessed). The defaults are counterintuitive, and getting fetch types wrong is one of the top causes of performance problems and LazyInitializationException in JPA applications. Default Fetch Types Annotation Default fetch type Performance risk @ManyToOne EAGER Loads related entity on every query — can be expensive @OneToOne EAGER Same — loads profile/address on every customer load @OneToMany LAZY Correct default — collections are only loaded when needed @ManyToMany LAZY Correct default The defaults for @ManyToOne and @OneToOne are EAGER — a poor choice that the JPA spec made for historical reasons.

Continue reading »

Filtering Messages with RecordFilterStrategy

Why Filter at the Container Level? Multiple consumers can share a topic. The inventory service only cares about PLACED orders; the analytics service wants everything. Rather than putting if (event.getStatus() != PLACED) return; at the top of every listener, Spring Kafka lets you filter records before they reach your method — keeping business logic clean and making the filter reusable across listeners. How RecordFilterStrategy Works flowchart LR Broker -->|"poll() → [r1, r2, r3, r4]"

Continue reading »