Katkat

Java, Spring & Kafka Fundamentals Deep-Dive

Wells FargoSoftware Engineer · Technical Screen

Last updated

Tests practical knowledge of Java concurrency and memory visibility, Kafka at-least-once delivery and idempotency patterns, and Spring Security context propagation across asynchronous thread boundaries.

Scenario: Reliable Asynchronous Transaction Processing Service

You are tasked with reviewing and stabilizing a high-throughput payment ingestion microservice built with Java 17, Spring Boot 3, and Apache Kafka. The service consumes payment authorization events from a Kafka topic (payment-authorizations), enriches each event with user risk data asynchronously via an internal REST client, and persists the final transaction to an RDBMS (PostgreSQL).

During peak load testing, the team identified three critical defects:

  1. Security Context Loss: Downstream calls made inside asynchronous tasks fail with 401 Unauthorized because the Spring SecurityContext is missing.
  2. Duplicate Ledger Postings: Under network jitter and consumer group rebalances, multiple instances process the same Kafka record, causing duplicate debit records in the database.
  3. State Corruption & Leaks: An internal in-memory metrics cache using a standard HashMap intermittently corrupts counts or throws ConcurrentModificationException.

Provide concrete architectural and implementation strategies to resolve each issue.

Questions to Address

1. Spring Security & Thread Context Propagation

  • Explain why SecurityContextHolder.getContext() returns an unauthenticated or empty context inside child threads spawned by CompletableFuture.supplyAsync() or a custom ThreadPoolTaskExecutor.
  • Detail two ways to properly propagate security credentials across thread boundaries in Spring Boot, including the specific risks associated with SecurityContextHolder.MODE_INHERITABLETHREADLOCAL when thread pools are reused.

2. Kafka Delivery Semantics & Idempotent Processing

  • Explain the default consumer offset commit behavior in Spring Kafka (enable.auto.commit=true vs AckMode.MANUAL_IMMEDIATE). Why does at-least-once delivery cause duplicate processing during consumer rebalances?
  • Propose an end-to-end idempotency strategy to ensure that duplicate Kafka deliveries never result in duplicate database writes. Include the database constraints and state check mechanism you would employ.
  • How should the consumer handle a unrecoverable "poison pill" payload without blocking partition processing indefinitely?

3. Java Concurrency & Transactional Boundaries

  • Contrast the thread-safety and performance characteristics of ConcurrentHashMap, Collections.synchronizedMap(), and using a ReentrantLock for high-concurrency read-heavy metrics tracking.
  • What happens if a database commit succeeds inside a @Transactional Spring service method, but the Kafka offset commit subsequently fails? How do you resolve dual-write inconsistency between Kafka and the database?

Hints

Hint 1

Consider how Spring's `DelegatingSecurityContextAsyncTaskExecutor` or `SecurityContextCallable` manages context cleanup when thread pool worker threads are returned to the pool.

Hint 2

For Kafka duplicate handling, evaluate unique constraint deduplication tables or the transactional outbox pattern combined with an idempotent consumer check.

Hint 3

Remember that `ConcurrentHashMap` utilizes lock striping and compare-and-swap (CAS) primitives on bucket heads, avoiding a global mutex.

Follow-up questions

  • If your Kafka consumer group rebalances while a batch of messages is actively being processed by worker threads, how do you prevent split-brain processing of the same partition?
  • How does Spring Kafka's `DefaultErrorHandler` with backoff and Dead Letter Publishing (DeadLetterPublishingRecoverer) prevent poison-pill deadlocks?
  • If you needed strictly ordered transaction processing per bank account, how would you partition the Kafka topic and configure the Spring `@KafkaListener` concurrency?