Skip to main content

r/SpringBoot


Building with the Latest Java Development Stack: Spring Boot 4.1.0, Java 25, Docker 29.5.3, PostgreSQL, Gradle 9.6.0, Eclipse 2026–06, Swagger/OpenAPI, Serenity, Cucumber, and JUnit 6
Building with the Latest Java Development Stack: Spring Boot 4.1.0, Java 25, Docker 29.5.3, PostgreSQL, Gradle 9.6.0, Eclipse 2026–06, Swagger/OpenAPI, Serenity, Cucumber, and JUnit 6
How-To/Tutorial

I recently updated my hands-on tutorial on building a complete working project with the latest Java development stack.

The article covers Spring Boot 4.1.0, Java 25, Docker 29.5.3, PostgreSQL, Gradle 9.6.0, Swagger/OpenAPI, Serenity, Cucumber, and JUnit 6 — all combined in one practical project.

The goal was to use the latest versions across the stack and show how they work together in a real Spring Boot application, using a vibe-coding approach.

Article title:

Building with the Latest Java Development Stack: Spring Boot 4.1.0, Java 25, Docker 29.5.3, PostgreSQL, Gradle 9.6.0, Swagger/OpenAPI, Serenity, Cucumber, and JUnit 6

A practical hands-on tutorial showing how to combine the latest Java, Spring Boot, Docker, PostgreSQL, Gradle, Swagger/OpenAPI, Serenity, Cucumber, and JUnit 6 in one working project using a vibe-coding approach.

Link:

https://medium.com/@anatolykrivitsky/quick-tutorial-how-to-use-the-latest-docker-29-5-2-0670b716b6cc?postPublishedType=repub

Hope it is useful for Spring Boot and Java developers.


Georgia knows weddings. Copilot knows Word.​
media poster


An HTTP call inside a @Transactional method quietly took down my whole API under load
An HTTP call inside a @Transactional method quietly took down my whole API under load
Discussion

Solo dev here, running a Spring Boot 3.4 backend in production (~25k users). Sharing a bug that taught me a lot.

My Stripe webhook handler did a retrieveSubscription() (an outbound HTTP call to Stripe) inside the same u/Transactional boundary that wrote to the DB. Looks innocent. Works fine normally.

Then Stripe had a brief hiccup and started retrying. The Stripe SDK's default read timeout is ~80s. So every retried webhook held a Hikari connection open for up to 80 seconds while waiting on a network call that wasn't even touching the database. Pool size was 60. It drained in seconds, and the entire API started returning 503 — nothing to do with Stripe.

Two fixes:

  1. Immediate: pin the SDK timeouts (5s connect / 15s read + 2 retries) so a stuck call can't hold a connection forever.

  2. Structural: get the HTTP call out of the transaction entirely, do the external call first, then open a short u/Transactional only for the DB write.

The general rule I now follow: a database connection is a scarce, pooled resource. Never hold one open across an external I/O call. It turned out I had the same anti-pattern in a few other places (Google token refresh, LGPD erasure with N revoke calls) and fixed them all the same way.

Curious how others structure this, do you split into "HTTP outside, TX inside" two-phase methods, or push the external calls fully async via an outbox? I went two-phase for the webhook and outbox for the Google sync.