first of all, thanks for sharing your concerns and ideas. This is exactly the reason why we decided to share our ideas up front. Unfortunately, whenever sharing ideas, we don’t always get to tell the whole story with all its context and considerations. What you saw in the presentation was merely a summary of our conclusions.
Let me share a few considerations here to give you some more background on what we’re planning on doing and why.
Working on Axon Framework for over 12 years has taught me a lot about API design. Throughout these 12 years, we’ve had four major releases where each time, we’ve changed to APIs to cope better with the types of applications that are built on top of it. More often than not, these are applications with demanding performance characteristics. Still, quite a few of the Axon Framework internals rely on the specific usage of threads. This is quite unfortunate in cases where message handler, for example, need to perform some asynchronous tasks.
Working with asynchronous tasks synchronously is a lot easier than the other way around. If that weren’t true, Loom would have been part of Java 9 . Therefore, all our internals need to be async-first. There will be multiple ways to deal with asynchronous code. We don’t want to make ourselves dependent on a project of OpenJDK that has been postponed (for good reasons) several times already. We also see that traditional async with CompletableFuture has severe limitations. That’s why we opted for Reactive.
But Axon, like any framework, is an onion. It has a lot of layers. In fact, we’ll be adding more layers. The plan is to make the core use Reactive, most likely project Reactor. We’ve already done some proofs of concept and found that the code will be a lot easier to digest.
Some of the layers around this core will still use the Reactive APIs. For example, we expect the Repository interface as well as the CommandBus and EventStore to return Flux or Mono. This way, we can make sure that people who wish to use this asynchronous approach still have the ability to do so. After all, for these components, location transparency is an essential ingredient.
But then come the outer layers of our onion. This is where things won’t actually change as much. For the annotated approach, we actually think we can be 100% backward compatible. You’ll be able to annotate a method and not worry about anything going on asynchronously in the framework.
But there will be subtle differences. For example, from these annotated methods, you can return a CompletableFuture, a Mono or Flux, or any other implementation of Publisher, for that matter, and Axon will be able to handle the asynchronous execution of your handler gracefully. Right now, whenever you’re able to return such a construct, the framework is forced to block and wait for a response.
But besides the annotated API, we’re also working on more declarative APIs to use Axon Framework. At their core, they will use a reactive style, but again, you can choose to use an extra layer of onions and keep it more procedural/traditional.
I hope this clarifies things a little bit better. Curious to find out what you think.