Clean Onion Architecture with Axon

Hello
I am new in axon and also DDD and Clean Architektur. I have done in production one Microservice with my understanding of DDD Clean resp. Onion architecture. It was a hobby many years already;) now I play again with axon to think about use it in one Microservice also to learn.

I ask my self now where to put the classes. The Axon Aggregate annotation will trigger me
to put it on the Domain package. put what will come
in the application package? I ask
my self ;).

the Read Api i see in the Infrastructure Package :wink:

for info I want
go with the mongodb Extension because to get Axon service or cloud in the company is not just easy.

Is there maybe some
samples with axon and Onion architecture ?

HI @c3smonkey in my projects I use Hexagonal architecture which is pretty similar on how to organize the code so I hope the structure I will present below may clarify your doubts and also serve to other to not only follow but also criticize and help the community to make it better

I have decide to split the service into two main packages/namespaces: commandmodule and querymodule and under each the following sub-packages: application, domain and infrastructure

The base package structure that I follow and regarding Axon I choose to distribute the classes like this:

### Command Model / Domain Model ###
application
+
|
+--> client
     +
     |
     +--> CientApplicationService
          commands
          +
          |
          +--> CreateClient
               ChangeClientEmail
domain
+
|
+--> client
     +
     |
     +--> Client (the aggregate)
          events
          +
          |
          +--> ClientCreated
               ClientEmailChanged
               
infrastructure
+
|
+--> http
     +
     |
     +--> external-service
          +
          |
          +--> all-http-related api used on support our domain
     messaging
     +
     |
     +--> external-services
          +
          |
          +--> ExternalServicesMessageListerner
          
### Query Model / Read Model  ###
application          
+
|
+--> client
     +
     |
     +--> ClientProjector
     
domain
+
|
+--> client
     +
     |
     +--> ClientView (JPA entity or Mongo document)
     
infrastructure
+
|
+--> http
     +
     |
     +--> client
          +
          |
          +--> ClientAPI
     messaging
     +
     |
     +--> client
          +
          |
          +--> ClientEvtHandler (Axon Event Handlers)

In this way I can protect my domain mainly from implementation details while concentrate the use-cases in the application package.

2 Likes

@habutre thanks a lot. You also use maybe HATEOAS API with axon… I am not sure if this really fit together.

Here is my POC at the moment… welcome for feedback :slight_smile:

HATEAOS on command side I give _Links with the URLs for the query side.

IMO it should be considered an implementation detail as I don’t see any reason from Axon that could prevent HATEOAS to be used

As I could see in your PoC you are using it, from my side I am not using HATEOAS but a simple REST controller wired by my projectors - so many implementations are possible without affect the Axon usage

1 Like

Yes I stumbled over the separation of Command /. Query and so far I hear a command should not give back any response… here is also talk I saw… in this case with spring where the HATEOAS is used to describe the commands and so on… The Future of Event-driven Microservices with Spring Cloud Stream by Kenny Bastani - YouTube

I think I will push the Axon Framework in my company for a little use case… with the MongoDb Setup i really like it so far also with the metrics endpoints.

what I also love is the separation of views.
I our company we have 3 difference clients iOS Android and Web.

My experience with Commands is mostly based on events from messaging brokers firing commands on my service but your API would play a similar role. Axon commands does not return anything but feedback about the execution throwing exception when not succeeded

Maybe you could thinking about fire-n-forget API calls when invoking commands in your service and HATEOAS API when reading from view model APIs

I hope it can give you some insights to move forward

1 Like