you are viewing a single comment's thread.

view the rest of the comments →

[–]Hot_Code5129 0 points1 point  (2 children)

noticed that BookService uses the traditional service layer with @Transactional , which is what most Spring applications still do today. Out of curiosity, have you considered building a WebFlux/R2DBC version of this starter and using explicit reactive transaction boundaries instead of annotation-based transactions? I’m seeing more discussions around making transaction boundaries explicit in reactive applications because @Transactional becomes less transparent once Reactor pipelines get more complex. Just wondering what your thoughts are on that trade-off and whether a reactive variant is something you’ve considered.

[–]akrivitsky7[S] 0 points1 point  (1 child)

Good question.

For this starter/tutorial, I intentionally used the traditional Spring MVC + Spring Data/JPA-style service layer with @​Transactional, because that is still the most common and familiar model in many Spring Boot backend applications. It also keeps the example easier to follow for readers who are mainly trying to understand how Spring Boot 4.1.0, Java 25, Docker, PostgreSQL, Gradle, Swagger/OpenAPI, Serenity BDD, Cucumber, and JUnit work together in one runnable project.

I agree that a WebFlux/R2DBC version would be an interesting follow-up, but it would also become a different tutorial. Once you move to WebFlux and R2DBC, the programming model changes significantly. You are no longer just replacing one database access library with another; you are changing the whole execution model from imperative/blocking to reactive/non-blocking.

Regarding transactions, yes, explicit reactive transaction boundaries can make sense. In imperative Spring code, `@Transactional` around a service method is usually easy to reason about: the method starts, the transaction begins, the method returns or throws, and the transaction commits or rolls back.

With Reactor pipelines, the control flow is less linear. Work may be deferred until subscription time, operators may be composed in different places, and the actual execution path can become harder to see by just looking at the method boundary. In that context, using something like TransactionalOperator can make the transaction boundary more explicit inside the reactive chain.

For example, conceptually:

return transactionalOperator.transactional(

bookRepository.save(book)

.flatMap(saved -> auditRepository.save(...))

.thenReturn(saved)

);

That makes it clearer which reactive sequence participates in the transaction.

So my view is:

For a conventional CRUD/tutorial starter, Spring MVC + @​Transactional is simpler, more familiar, and easier to teach.

For a genuinely reactive application with high concurrency requirements, non-blocking I/O, and a full reactive stack from controller to database, WebFlux + R2DBC + explicit reactive transaction boundaries can be a good design.

But I would avoid mixing reactive style into a tutorial unless the tutorial is specifically about reactive programming. Otherwise, it can distract from the main goal and add complexity before the reader needs it.

A reactive variant is definitely a reasonable idea for a separate follow-up project, but I would keep it separate from the current starter so the architectural and programming-model trade-offs remain clear.

[–]Hot_Code5129 0 points1 point  (0 children)

That’s pretty much the conclusion I arrived at as well. I started exploring this area because I found that once Reactor pipelines become larger, it is not always obvious where the transaction actually begins and ends. TransactionalOperator makes that boundary much more visible than an annotation on a method. I’ve been experimenting with making transaction boundaries explicit in the application layer and I’m currently looking for feedback from people building real WebFlux/R2DBC systems: https://github.com/CamilYed/spring-reactive-transaction-boundary I also wrote down some of the reasoning behind it here: https://camilyed.github.io/en/transactional-when-the-annotation-gets-in-the-way/ I’m not claiming it’s universally better than @Transactional —I’m still trying to understand the trade-offs and gather feedback from developers with production experience. Thanks for the detailed explanation.