The End of the Reactive Java Era: Insights and Alternatives
Written on
Chapter 1: A Shift in Paradigms
The era of reactive Java has effectively concluded, a realization that many have come to, particularly with the introduction of Virtual Threads in Java 21. This new development has prompted reconsideration of the need for reactive frameworks like Spring WebFlux. While I may be stating the obvious, I feel compelled to share my thoughts to help others avoid the pitfalls of reactive programming when it's unnecessary.
Experts on Reactive Java
Understanding the benefits and drawbacks of reactive programming often requires an in-depth analysis of large-scale projects and the challenges that arise during modifications. Fortunately, experts have navigated this terrain, allowing us to learn from their insights. The maintainers of libraries are among the most knowledgeable in this area. Here are some noteworthy quotes from their documentation:
“If your Spring MVC application is functioning well, there's no reason to switch. Imperative programming is the simplest approach for writing, comprehending, and debugging code. You also have a broader selection of libraries, as most have historically been blocking.” — Spring
This statement is quite telling, especially in the context of a reactive framework. Let's add this to our list of disadvantages: increased complexity in writing, understanding, and debugging code, coupled with a reduced library selection.
“The primary anticipated advantage of reactive and non-blocking approaches is the capability to scale using a limited number of threads and lower memory consumption.” — Spring
This is a valid point, and improved scalability should indeed be recognized as a benefit. Now, let’s consider insights from Java Language Architect Brian Goetz regarding reactive Java from a few years ago.
“We will discover that reactive is a transitional technology. Initially, we may have thought we liked reactive programming, but it turns out it has significant drawbacks, and we only preferred it because the alternatives were worse.” — Java Futures with Brian Goetz (More detailed explanation by him here)
Essentially, if you were reliant on performance, reactive programming might have appeared to be a viable alternative. However, with greater knowledge, we realize its shortcomings. Goetz elaborates on these shortcomings in another video, where he points out the trade-offs required for better scalability. Developers must forfeit Java's control flow statements, simple loops, and the ability to debug code sequentially, as well as receive clear stack traces. Let's include these in our list of disadvantages.
Disadvantages: Increased complexity in writing, understanding, and debugging; fewer libraries; loss of Java control flow statements; challenges in sequential debugging and obtaining clear stack traces.
Advantages: Improved scalability.
The claim of better scalability may have held true for older Java versions. However, with the recent release of Java, virtual threads have emerged, allowing traditional Java to scale more effectively. Therefore, we should amend our list of advantages.
Advantages: Slightly enhanced scalability.
In summary, reactive Java has a limited theoretical space where performance demands are exceptionally high.
My Experience with Reactive Java
My personal experiences align closely with expert opinions. The code is often challenging to read, and there's a steep learning curve associated with writing it. Managing transactions serves as a prime example of how things become more complicated, as it's difficult to group database calls needing to be executed within the same transaction scope. I have witnessed blocking libraries being transformed into non-blocking ones, which resulted in production bugs due to the inherent complexity of the task. Given my current environment, where performance isn't a pressing concern, I struggle to see how the advantages outweigh the disadvantages.
The Future of Java Frameworks
I find it surprising that frameworks like Spring Boot and Quarkus have adopted this paradigm so vigorously. They now find themselves tied to reactive APIs to maintain support for existing users. If you're contemplating exploring alternative frameworks, this might be an opportune moment. For those requiring high performance, consider looking into Rust. Although it also comes with a steep learning curve, it offers a language designed to address your challenges rather than forcing a new paradigm onto Java.
For those interested in transitioning from reactive Java to standard Java, a forthcoming post will delve deeper into this topic. Stay tuned for updates!
Chapter 2: Insights from the Experts
In this video titled "Codemotion Madrid 2019 I The Reactive Revolution," experts discuss the implications of reactive programming and its evolution.
The second video, "Keeping Up with Java • Sander Mak • GOTO 2018," features a discussion on the current state and future prospects of Java programming.