Systems
Services that run. Distributed transactions, message brokers and the failure modes that come with them.
- tripsaga A distributed booking saga over RabbitMQ. Flight, hotel and payment services settle all-or-nothing, or every step that succeeded is compensated. Orchestration, not choreography — the orchestrator is a durable state machine.
- nhx-finance/nhx-kesy Backend for a Hedera-based stablecoin issuance platform. Secure, event-driven services with RBAC enforcing strict separation between issuing companies and platform administrators, plus KYC verification, minting endpoints and Flyway migrations.
- smartcart An AI-assisted storefront. Semantic product discovery that survives vague search terms, personalised recommendations from purchase history, and generated product copy.
Run the saga
TripSaga in miniature. The orchestrator sends a command, waits for the reply event, then advances. Break it at any step and watch every step that already succeeded get reversed — that is the whole point of a saga.
Teaching
Repositories built to be read. Each one is a runnable answer to a question I kept getting asked.
- java-for-everyone Learn Java from the ground up — a sequential curriculum covering syntax, OOP, collections, streams and lambdas, with guides, code samples and exercises.
- spring-rabbitmq Hands-on RabbitMQ with Spring Boot — nine lessons from your first message to publisher confirms, manual acks and dead-letter exchanges.
-
exception-handling
Production-grade exception handling — from a custom
ErrorResponseDTO all the way to a fully RFC 9457ProblemDetailarchitecture. Every endpoint is runnable. - springai Spring AI notes and runnable samples against models deployed on Azure AI Foundry — prompts, structured output, embeddings and vector search.
- spring-boot-4-http-interfaces Call another API by writing a Java interface and let Spring write the client. Includes the two things most demos skip: timeouts and retries.
Move a message
The broker from spring-rabbitmq, in miniature. Turn confirms off and the publisher stops learning whether the broker ever had the message. Crash the consumer and nothing is lost — it comes back, three times, and then the dead letter exchange takes it.
Throw something
The error handling from exception-handling, in miniature. The
request descends the layers, something throws, the frames unwind untouched — no
try/catch anywhere — and one @ControllerAdvice turns whatever arrived
into an RFC 9457 ProblemDetail. Change the exception and only the
response changes.