Two Testing Strategies Strategy Speed Fidelity Use when @EmbeddedKafka Fast (~2s startup) In-process broker, not 100% identical Unit/integration tests — CI fast path KafkaContainer (Testcontainers) Slower (~10s startup) Real Kafka broker in Docker Acceptance tests, DLT/transaction validation Use both: @EmbeddedKafka for the bulk of tests, KafkaContainer for the smoke suite that validates real-broker behaviour. Test Dependencies <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.testcontainers</groupId> <artifactId>kafka</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.awaitility</groupId> <artifactId>awaitility</artifactId> <scope>test</scope> </dependency> @EmbeddedKafka — Fast Integration Tests Testing a Producer @SpringBootTest @EmbeddedKafka( partitions = 1, topics = {"orders"}, brokerProperties = {"log.
Continue reading »Spring-Boot
209 posts in this section
Testing Spring Data JPA: @DataJpaTest, Testcontainers, and Best Practices
Why Test JPA Code? Unit tests with mocked repositories verify your service logic but nothing about the database. They won’t catch: Wrong column mapping Constraint violations N+1 queries introduced by a new lazy association Transactions that silently don’t roll back Queries that fail on the real database but pass on H2 Testing against a real database — or at minimum a database-compatible in-memory store — is necessary. Spring Boot’s @DataJpaTest and Testcontainers make this practical.
Continue reading »Testing Spring Security: @WithMockUser, MockMvc, and SecurityMockMvc
Why Security Tests Are Non-Negotiable A security configuration that is never tested is a security configuration that is probably wrong. URL patterns have subtle ordering rules. Method security annotations are silently ignored if @EnableMethodSecurity is missing. CSRF tokens must be present in the right form. Testing is the only way to know your authorization rules are actually enforced. Test Dependencies <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> @WithMockUser The simplest way to simulate an authenticated user.
Continue reading »The N+1 Problem: Detection, Root Cause, and All Solutions
What Is the N+1 Problem? The N+1 problem occurs when loading a list of N entities triggers N additional queries to load their associations — one query per entity. Example: load 50 orders, then access each order’s customer: SELECT * FROM orders; -- 1 query SELECT * FROM customers WHERE id = 1; -- query for order 1's customer SELECT * FROM customers WHERE id = 2; -- query for order 2's customer SELECT * FROM customers WHERE id = 3; -- query for order 3's customer .
Continue reading »The Persistence Context: How JPA Tracks Your Entities
Introduction The persistence context is the single most important concept in JPA. Everything else — lazy loading, dirty checking, transaction scope, detached entity exceptions — only makes sense once you understand what the persistence context is and how it works. Many JPA bugs come from developers not understanding this concept. Understand it well and the rest of JPA becomes predictable. What Is the Persistence Context? The persistence context is an in-memory map of entities managed by the current EntityManager.
Continue reading »The Security Filter Chain: Every Filter Explained
Every Filter Has a Job The Spring Security filter chain is not a monolith — it’s 15-20 individual filters, each responsible for exactly one concern. Understanding each filter’s job means you can: Know exactly where in the chain a request fails Add your own filter in the right position Remove filters you don’t need for performance Debug authentication and authorization problems The Complete Filter Order Spring Security defines a strict ordering for its filters.
Continue reading »Transaction Boundaries and Common Pitfalls
Transaction Boundaries A transaction boundary is the point where a transaction starts and where it ends. In Spring, boundaries are defined by @Transactional on service methods. HTTP Request └── Controller (no transaction) └── @Transactional Service method ← transaction OPENS here ├── Repository call 1 ├── Repository call 2 └── method returns ← transaction COMMITS here Everything inside the @Transactional method runs in the same database transaction. The persistence context (first-level cache) lives for the duration of that transaction.
Continue reading »What Is Apache Kafka: Event Streaming From First Principles
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 »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 »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 »