Axxes IT Consultancy

Een introductie tot het Axon Framework

Ondertussen is Axon in de Java wereld uitgegroeid tot een populaire keuze om event-driven microservice systemen te implementeren. Reden genoeg om onze Axxes Java consultants samen te brengen voor een opleiding Axon. Toen ik persoonlijk de uitnodiging in m’n inbox kreeg, had ik geen idee waaraan we ons mochten verwachten. Een snelle Google opdracht gaf aan dat het om een Java Domain Driven Design framework ging, maar verder besloot ik me helemaal te laten verrassen. Hierbij een introductie:

Wat is Axon?

Axon is zoals reeds vermeld een framework dat ontwikkelaars de belangrijkste bouwstenen levert om een Java applicatie te implementeren volgens de Domain Driven Design principes, het legt hierbij de nadruk op Event Sourcing en CQRS. Hot topics in de context van microservice architectuur.

De aanzet voor het framework werd reeds enkele jaren geleden gegeven in de vorm van een open-source hobbyproject. Ondertussen is Axon een populaire manier om een event-driven microservice systemen te implementeren en mag het zowel startups als grote ondernemingen, zoals Barclays, Toyota en UPS tot het cliënteel rekenen.

Reden genoeg dus voor onze coaches om ons kennis te laten maken met het product. We hadden ook het voorrecht de geestelijke vader, en huidig CTO, Allard Buijze tot één van onze instructeurs te mogen rekenen voor onze hands-on training.

DDD

De opleiding begon met een korte opfrissing van de DDD concepten zoals gedefinieerd door Eric Evans in zijn gelijknamig boek. Na de blokken theorie volgde meteen een modelleringsoefening door middel van het kaartspelletje “Presidenten” om dit conceptueel model aan de praktijk te toetsen. Domain Driven denken vraagt immers een denkmatige paradigmaverschuiving t.o.v. een Object Oriented ontwerp.

Domain Driven Design pleit ervoor software te modelleren in termen van reële use cases uit de business. Het concept mag dan al even de hype voorbij zijn, maar deze aanpak is uiterst efficiënt bewezen om via een analyse in business termen tot een universeel betekenisvolle oplossing te komen. Bij het ontwerpen van DDD software is het de bedoeling om problemen per (sub)domein te gaan analyseren. Verschillende onafhankelijke stappen of gebieden van het probleem worden door middel van een universele taal uitgedrukt als een bounded context, waarbij ook heel wat technische concepten als entities, value objects en aggregates worden gebruikt om de software te modelleren. Voor alle details verwijs ik graag naar het boek ‘Domain-Driven Design’ van Eric Evans.

Hoe past Axon nu in dit plaatje, welke tools voorziet het framework? Met Axon kan je domein objecten in het aggregaat manipuleren door middel van commands die op hun beurt tot events leiden. Een command wordt gebruikt om de staat van het aggregaat te wijzigen, het bevat alle nodige informatie om de wijziging uit te voeren. Ieder command wordt afgehandeld door een Command Handler. In een Command Handler wordt de wijziging geverifieerd en een methode uitgevoerd die de state van het aggregaat wijzigt. Een command kan ook worden geweigerd. Wanneer de state van een aggregaat wijzigt, wordt een event afgevuurd. Events worden afgehandeld door Event Handlers. Een event duidt op een wijziging aan het aggregaat die al werd doorgevoerd. Gezien het verleden niet kan worden gewijzigd, moeten events niet gevalideerd of verworpen worden. Enkel de events worden in de event store opgeslagen. De staat van een aggregaat is vluchtig, maar kan altijd opgebouwd worden vanuit de event store.

Event Sourcing

Het basis idee achter Event Sourcing is om elke wijziging aan de staat van een applicatie op te slaan in termen van gebeurtenissen in plaats van de huidige staat, het opslaan van deze event log gebeurt in een event store. Zoals reeds vermeld zijn events gebeurtenissen die reeds plaatsvonden en kunnen ze, eens ze bestaan, niet worden uitgewist. De huidige applicatiestaat kan dan opgebouwd worden door alle geregistreerde events sequentieel na elkaar af te spelen.

Retroactieve wijzigingen of een simulatie van een applicatiestaat kunnen worden uitgevoerd door een kopie te nemen van de events tot op een bepaald punt en hierop een alternatieve serie van events uit te voeren om zo de alternatieve werkelijkheid te bekomen zonder de huidige staat te wijzigen. Event based systems zijn dus uitermate geschikt voor calculation engines en financiële toepassingen.

Door de business flow uit te drukken in termen van events is het relatief eenvoudig om de applicatie te schalen naar bijkomende modules die op de staat wijzigen moeten reageren. Doordat een event op zich geen applicatielogica bevat, moet er enkel voor gezorgd worden dat de bijkomende logica reageert op de specifieke applicatie events.

Een bijproduct van het opslaan van de staat in termen van sequentiële events is dat een complete historiek van alle wijzigingen van de applicatiestaat aanwezig zijn. Voor elk moment in het verleden kan bepaald worden wat de situatie was op dat precieze tijdstip. Het nadeel is dan weer dat voor dergelijke temporele query de staat telkens opnieuw moet worden opgebouwd door alle achtereenvolgende events van het begin af tot op het gevraagde punt uit te voeren. Dit proces kan echter geoptimaliseerd worden door de huidige staat op te slaan op bepaalde momenten in de vorm van snapshots en deze tussentijdse staat te gebruiken als vertrekpunt om verdere events op af te spelen. Om meer specifieke queries te gaan uitvoeren, kunnen nog transformaties op de staatrepresentatie nodig zijn, en net hier komt CQRS op de proppen.

CQ(R)S

CQRS staat voor Command Query Responsibility Segregation. Het principe werd voor het eerst beschreven door Greg Young en stelt vrij eenvoudig dat je een verschillend model kan gebruiken om informatie te wijzigen en een ander om deze uit te lezen.

Bij traditionele architecturen wordt veelal voor een CRUD opslag geopteerd, waarmee bedoeld wordt dat één enkel model met één mapping naar de recordstructuur wordt gebruikt om nieuwe records aan te maken, deze te lezen, aan te passen of te verwijderen. In de meest eenvoudige gevallen zullen alle interacties enkel inhouden dat informatie in deze records worden opgeslagen of opgehaald.

Naargelang dit enkelvoudig model complexer wordt, wanneer bijvoorbeeld meerdere records worden samengevoegd of virtuele records worden gemaakt door informatie uit verschillende domeinen te combineren. Of wanneer validatie regels worden toegevoegd die bepalen welke datacombinaties kunnen worden opgeslagen, of zelf afgeleide data wordt gepersisteerd. In deze situaties zullen we verder van dit eenvoudige model gaan afwijken, en dreigt het model dus al snel een heuse Frankenstein te worden.

Een ander potentieel probleem is dat bij lezen en schrijven de workloads vaak asymmetrisch zijn met zeer verschillende, zelfs contradictorische vereisten qua prestaties en schaalbaarheid van het model. Dit is zeker ook het geval voor onze DDD toepassingen. Om de huidige staat van de toepassing te kennen, moeten events telkens achtereenvolgend op elkaar toegepast worden.

CQRS gaat deze problemen uit de weg door de  modellen af te splitsen in een schrijf- en leesmodel, een command- en querymodel. Commands zijn taakgebaseerd in plaats van data-afhankelijk en kunnen asynchroon door de verschillende deelsystemen (domeinen) verwerkt worden. Queries van hun kant zullen nooit wijzigingen aan de data uitvoeren.

Wanneer we deze afsplitsing verder doortrekken, kan de lees- en schrijfdata ook fysiek van elkaar gescheiden worden. In dit geval kunnen de query datastores eigen schema’s definiëren die geoptimaliseerd zijn voor bepaalde leesbewerkingen. Het is dus niet enkel mogelijk meerdere representaties van de informatie aan te bieden, er kan zelfs een compleet ander type datastore gebruikt worden. Zo kan de ene query view een relationele database betreffen en een andere informatie uit een document database opvragen.

Wanneer verschillende command- en query datastores worden gebruikt, moeten deze uiteraard in sync blijven. Daarom zal bij het uitvoeren van een command een event worden gepubliceerd. Wanneer de event store wordt geüpdatet, zullen ook binnen dezelfde transactie de transformaties op de bijhorende query data in gang worden gezet. Ons probleem met het bepalen van de huidige staat van de toepassing kan op deze manier gemakkelijk worden opgelost. Als we consequent bij het ontvangen van een event de nodige query data aanpassen kan zo een view worden gemodelleerd die de huidige toestand meteen kan weergeven.

Architecture overview of a CQRS application - Axon Framework

Bron: Axon Framework

Conclusie

Axon biedt alle bouwstenen om DDD te introduceren in een Java applicatie. Dit was de eerste keer dat ik een opleiding DDD kreeg, die zo toegespitst was op de praktische in plaats van enkel de theoretische aspecten. Om dit meer concreet te maken, gaan we in een volgende blogpost een applicatie op basis van het Axon framework toelichten. Dit zal de concepten (Commands, Events, CQRS) van deze post in code tonen.

Over de auteur

Birger Anckaert

Birger Anckaert

Agile Java / Web Consultant

Deel dit artikel

LEER ONS BETER KENNEN

Maak alvast beter kennis met Axxes en onze bedrijfscultuur!

Ben je op zoek naar expertise of ben je zelf een Axon fanaat?

Neem contact op.

Blijf op de hoogte van nieuws en updates in de sector