Spring-Boot

209 posts in this section

Consumer Groups, Offsets, and the __consumer_offsets Topic

What Is a Consumer Group? A consumer group is a set of consumer instances that jointly consume a topic. Kafka assigns each partition to exactly one consumer within the group at a time. This is what enables parallel processing: multiple consumers in the same group read different partitions simultaneously. flowchart LR subgraph Topic["Topic: orders — 4 partitions"] P0["Partition 0"] P1["Partition 1"] P2["Partition 2"] P3["Partition 3"] end subgraph CG["Consumer Group: inventory-service"] C1["

Continue reading »

Consumer Groups: Parallel Processing and Partition Assignment Strategies

Consumer Group Fundamentals A consumer group is how Kafka distributes work across multiple consumers. Each partition in a topic is assigned to exactly one consumer instance in the group at any given time. flowchart TB subgraph Topic["Topic: orders — 6 partitions"] P0["P0"] P1["P1"] P2["P2"] P3["P3"] P4["P4"] P5["P5"] end subgraph CG1["Group: inventory-service (3 instances)"] I1["Instance 1\nP0, P1"] I2["Instance 2\nP2, P3"] I3["Instance 3\nP4, P5"] end subgraph CG2["Group: notification-service (1 instance)"] N1["Instance 1\nP0,P1,P2,P3,P4,P5"] end P0 & P1 --> I1 P2 & P3 --> I2 P4 & P5 --> I3 P0 & P1 & P2 & P3 & P4 & P5 --> N1 Both groups receive all events — they are independent.

Continue reading »

CORS: Cross-Origin Requests and Preflight Configuration

What Is CORS? The Same-Origin Policy (SOP) is a browser security rule: JavaScript on app.example.com cannot read responses from api.example.com — different subdomain, different origin. Without this, any website could use a visitor’s authenticated session to silently call other sites on their behalf. CORS (Cross-Origin Resource Sharing) is the mechanism by which a server explicitly relaxes SOP for trusted origins. When a browser sees a cross-origin request, it checks whether the server has granted permission before allowing JavaScript to read the response.

Continue reading »

CSRF Protection: How It Works and When to Disable It

What Is a CSRF Attack? Cross-Site Request Forgery (CSRF) tricks an authenticated user’s browser into making an unintended request to your application. The attack: Alice is logged into bank.com — her browser holds a valid session cookie Alice visits evil.com evil.com contains <img src="https://bank.com/transfer?to=attacker&amount=5000"> Alice’s browser fires the request, automatically attaching her bank.com session cookie bank.com receives an authenticated request that Alice never intended to make The attack works because browsers automatically send cookies with cross-origin requests.

Continue reading »

Custom Queries with @Query: JPQL and Native SQL

Why @Query Exists Derived query methods (Article 17) are great for simple conditions, but they break down fast. A method like findByOrderStatusAndCustomerCityAndPriceBetweenOrderByCreatedAtDesc is unreadable and still cannot express a JOIN or aggregation. @Query lets you write the exact JPQL or SQL you need, attached directly to a repository method — keeping your repository clean while giving you full query control. JPQL vs Native SQL JPQL Native SQL Language Entity/field names Table/column names Database portable Yes No JOIN FETCH Yes No Window functions No Yes Full-text search No Yes Complex analytics Limited Full power Start with JPQL.

Continue reading »

Custom Serializers and Deserializers

When to Write a Custom Serializer Spring Kafka ships JSON and Avro support. You need a custom serializer when: Your team uses Protobuf or MessagePack and wants native support You need a compact binary format for high-throughput topics (pricing ticks, sensor readings) You’re integrating with a legacy system that publishes a fixed binary protocol You want deterministic serialization for event deduplication or content-addressed storage The Serializer and Deserializer Interfaces // org.

Continue reading »

Custom Type Conversions: AttributeConverter and Enums

Introduction JPA handles most Java types automatically — String, Integer, LocalDate, BigDecimal. But what about a Java enum? A List<String> stored as JSON? A custom Money type? JPA’s AttributeConverter and @Enumerated let you control exactly how any Java type maps to a database column. Mapping Enums with @Enumerated Java enums are common in domain models. JPA maps them with @Enumerated: public enum OrderStatus { PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED } public enum ProductStatus { ACTIVE, INACTIVE, DISCONTINUED } @Column(length = 20, nullable = false) @Enumerated(EnumType.

Continue reading »

Dead Letter Topics: Routing Failed Messages with DeadLetterPublishingRecoverer

What Is a Dead Letter Topic? When a record fails processing and retries are exhausted, you have two options: skip it (losing the data) or park it somewhere for inspection and reprocessing. A dead-letter topic (DLT) is that parking lot — a Kafka topic that holds records that could not be processed, enriched with error metadata headers. flowchart LR subgraph Main["orders topic"] R1["record: offset 42\n(bad data)"] end subgraph DLT["orders.DLT topic"] R2["

Continue reading »

Derived Query Methods: Finding Data Without Writing SQL

Introduction Spring Data JPA can generate JPQL queries directly from method names. You declare a method like findByStatusAndPriceGreaterThan, and Spring Data parses the name, derives the query, and generates the implementation. No SQL, no @Query, no boilerplate. How Derived Query Parsing Works Spring Data JPA splits method names into a subject and a predicate: findBy Email And Status ↑ ↑ ↑ ↑ subject property operator property The subject determines the operation type (find, count, exists, delete).

Continue reading »

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 »