{"id":2608,"date":"2010-11-12T18:34:57","date_gmt":"2010-11-12T17:34:57","guid":{"rendered":"http:\/\/blog.jteam.nl\/2010\/11\/12\/tutorial-getting-started-with-cqrs-and-axon-framework\/"},"modified":"2010-11-12T18:34:57","modified_gmt":"2010-11-12T17:34:57","slug":"tutorial-getting-started-with-cqrs-and-axon-framework","status":"publish","type":"post","link":"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/","title":{"rendered":"Tutorial &#8211; Getting started with CQRS and Axon Framework"},"content":{"rendered":"<p><a href=\"http:\/\/www.axonframework.org\/\">Axon Framework<\/a> greatly simplifies building CQRS based Event Driven architectures in Java. Such an architecture provides very powerful options in terms of application scalability and extensibility. In this tutorial, I want to go though the process of setting up a basic application architecture with the Axon Framework.<\/p>\n<p><!--more-->Building a foundation for your application can be divided in roughly four steps. First, we need to set up the project infrastructure. Which modules to we need? Which dependencies? The second step is to define the core API. What do we want our application to do? How can we tell it to do those things? This is when the definition of the commands and events is made. Building the command handling component, the one that consumes commands and produces events, is the third step. Lastly, in step four, the query component is build that turns events into a queryable data source for your application\u2019s client.<\/p>\n<p>Although this tutorial explains the process in a serial fashion, once you have done step 2, the definition of the core API, one team could work on the command handling component, while another team works on the query component.<\/p>\n<p>In this tutorial, I will focus on the backend development. There is nothing special going on in the UI, other than that it will need to send commands and call a \u201cservice layer\u201d to execute queries.<\/p>\n<p>If you\u2019re getting stuck somewhere, or just want to take the easy route through this tutorial, you can download the sources at: <a title=\"http:\/\/axonframework.googlecode.com\/files\/axon_tutorial.zip\" href=\"http:\/\/axonframework.googlecode.com\/files\/axon_tutorial.zip\">http:\/\/axonframework.googlecode.com\/files\/axon_tutorial.zip<\/a><\/p>\n<h2>Step 1 \u2013 Project infrastructure<\/h2>\n<p>Before we can get started, we need to set up a basic project infrastructure. You can do this in any IDE and using any dependency management system you like to use, albeit maven, ant or just plain manual labor.<\/p>\n<p>To keep things, simple, we can use a single java source directory (src\/main\/java when using Maven). Inside we\u2019ll create a few packages that make it clear in which \u201cmodule\u201d we are working. In a real project, you\u2019d probably want to separate these packages over multiple modules\/jar files.<\/p>\n<p>Let\u2019s assume we are building an order management system for the Acme company. You need the following packages to get started:<\/p>\n<ul>\n<li>com.acme.oms.api \u2013 will contain the API classes (i.e. commands and events)<\/li>\n<li>com.acme.oms.commandhandling \u2013 contains the command handling classes<\/li>\n<li>com.acme.oms.query \u2013 contains the event handlers and query API<\/li>\n<\/ul>\n<p>You also need the following dependencies:<\/p>\n<ul>\n<li>org.axonframework:axon-core 0.7 (since 0.7 wasn\u2019t released yet at the time of writing, 0.7-SNAPSHOT was the version used in this tutorial)<\/li>\n<li>org.springframework:spring-context 3.0.5.RELEASE<\/li>\n<\/ul>\n<p>If you need database support, you&#8217;ll also need to add dependencies to spring-orm, hibernate-entitymanager and your database driver.<\/p>\n<p>For logging (this tutorial uses log4j):<\/p>\n<ul>\n<li>org.slf4j:slf4j-log4j 1.5.8<\/li>\n<li>org.slf4j:slf4j-log4j12 1.5.8<\/li>\n<li>org.slf4j:jcl-over-slf4j 1.5.8<\/li>\n<\/ul>\n<p>And for testing:<\/p>\n<ul>\n<li>junit:junit 4.8.1<\/li>\n<li>org.axonframework:axon-test 0.7<\/li>\n<\/ul>\n<p>Configuring these dependencies using Maven is the easiest way to also get the transitive dependencies.<\/p>\n<p>You application will also need a spring application context, which glues all infrastructure components together. What we need for now is some persistence configuration, and two infrastructure items Axon provides: the command bus and the event bus. Here is some contents of the application context<\/p>\n<p><pre class=\"brush: xml; title: ; notranslate\" title=\"\">&amp;lt;!-- Automatically find any command and event handlers in our application --&amp;gt;&lt;br&gt;\n    &amp;lt;ctx:component-scan base-package=&quot;com.acme.oms.commandhandling&quot; \/&amp;gt;&lt;br&gt;\n    &amp;lt;ctx:component-scan base-package=&quot;com.acme.oms.query&quot; \/&amp;gt;&lt;\/p&gt;\n&lt;p&gt;    &amp;lt;!-- Axon infrastructure --&amp;gt;&lt;br&gt;\n    &amp;lt;axon:annotation-config \/&amp;gt;&lt;br&gt;\n    &amp;lt;axon:event-bus id=&quot;eventBus&quot; \/&amp;gt;&lt;br&gt;\n    &amp;lt;axon:command-bus id=&quot;commandBus&quot; \/&amp;gt;<\/pre><\/p>\n<h2>Step 2 \u2013 Your application\u2019s core API<\/h2>\n<p>In this tutorial, we\u2019re going to keep it simple. The Acme company has a rather simplistic view on order management. The system should be allows to create orders. An order always contains a single product. Orders can be cancelled, and confirmed. Once an order is cancelled, it can no longer be confirmed.<\/p>\n<p>To build our API, we should focus on the activity of our application. What can we do, and what can happen?<\/p>\n<p>In this application, we can do three things, which leads us to the following commands:<\/p>\n<ul>\n<li>CreateOrderCommand<\/li>\n<li>ConfirmOrderCommand<\/li>\n<li>CancelOrderCommand<\/li>\n<\/ul>\n<p>Notice that all command are in the imperative tense. That\u2019s because we\u2019re telling the system to do something. Commands should be clear about what the user expects. Here is the code for one of the commands:<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">public class CreateOrderCommand {&lt;\/p&gt;\n&lt;p&gt;    private final String orderId;&lt;br&gt;\n    private final String productId;&lt;\/p&gt;\n&lt;p&gt;    public CreateOrderCommand(String orderId, String productId) {&lt;br&gt;\n        this.orderId = orderId;&lt;br&gt;\n        this.productId = productId;&lt;br&gt;\n    }&lt;\/p&gt;\n&lt;p&gt;    public String getOrderId() {&lt;br&gt;\n        return orderId;&lt;br&gt;\n    }&lt;\/p&gt;\n&lt;p&gt;    public String getProductId() {&lt;br&gt;\n        return productId;&lt;br&gt;\n    }&lt;br&gt;\n}<\/pre><\/p>\n<p>Note that the identifier of the order to create is included in the command. Client-provided identifiers are a powerful way to improve (perceived) performance in a client. A client sending this command does not need to wait for the server to return an identifier. All it needs is the confidence that the server will execute the command. Sometime\u2026<\/p>\n<p>Since our application is straightforward, the each event simply maps to one of the commands. Be aware that not every system allows such a simplistic approach. Listen carefully to your domain expert for hints of events.<\/p>\n<ul>\n<li>OrderCreatedEvent<\/li>\n<li>OrderConfirmedEvent<\/li>\n<li>OrderCancelledEvent<\/li>\n<\/ul>\n<p>Since all these events come from the \u201cOrder\u201d concept, let\u2019s create an abstract parent event called AbstractOrderEvent. Here is some code of the abstract event and one of its implementations:<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">import org.axonframework.domain.DomainEvent;&lt;\/p&gt;\n&lt;p&gt;public abstract class AbstractOrderEvent extends DomainEvent {&lt;br&gt;\n    public String getOrderId() {&lt;br&gt;\n        return getAggregateIdentifier().asString();&lt;br&gt;\n    }&lt;br&gt;\n}&lt;br&gt;\n<\/pre><\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">public class OrderCreatedEvent extends AbstractOrderEvent {&lt;\/p&gt;\n&lt;p&gt;    private final String productId;&lt;\/p&gt;\n&lt;p&gt;    public OrderCreatedEvent(String productId) {&lt;br&gt;\n        this.productId = productId;&lt;br&gt;\n    }&lt;\/p&gt;\n&lt;p&gt;    public String getProductId() {&lt;br&gt;\n        return productId;&lt;br&gt;\n    }&lt;br&gt;\n}&lt;br&gt;\n<\/pre><\/p>\n<p>The other events are quite similar. Note that the aggregate identifier in Axon\u2019s DomainEvent class contains the ID of the aggregate that published the event. In our case, that\u2019s the Order. So we don\u2019t need to add the order ID to our own event definitions. To make things more explicit, the AbstractOrderEvent contains a getOrderId(), which exposes this aggregate identifier using our own domain language.<\/p>\n<h2>Step 3 \u2013 Command Handling component<\/h2>\n<p>Now that we have our API, we can start building the command handling component. Well, if we really want to do it the right way, we can\u2019t. First, we should build our tests. For our command handling component, we&#8217;re going to use an event sourced aggregate, which makes things really easy to test.<\/p>\n<p>We have a few cases to test. When we send a CreateOrderCommand, we expect an order to be created. When we confirm an order, well, if we haven\u2019t cancelled it, we expect it to be confirmed. If it has been cancelled, we expect nothing to happen.<\/p>\n<p>Lets translate this to given-when-then tests in Axon. First, we need to set up the test fixture in the setUp (or @Before) method of a JUnit test. The empty shells of the necessary production classes can be created &#8220;on the fly&#8221;.<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">public class OrderCommandHandlerTest {&lt;\/p&gt;\n&lt;p&gt;    private FixtureConfiguration fixture;&lt;\/p&gt;\n&lt;p&gt;    @Before&lt;br&gt;\n    public void setUp() throws Exception {&lt;br&gt;\n        fixture = Fixtures.newGivenWhenThenFixture();&lt;br&gt;\n        OrderCommandHandler commandHandler = new OrderCommandHandler();&lt;br&gt;\n        commandHandler.setOrderRepository(fixture.createGenericRepository(Order.class));&lt;br&gt;\n        fixture.registerAnnotatedCommandHandler(commandHandler);&lt;br&gt;\n    }&lt;br&gt;\n}<\/pre><\/p>\n<p>We have injected a GenericRepository in our command handler. This allows the command handler to retrieve the correct domain object (an Order).<\/p>\n<p>Creating test cases is pretty straightforward from here. The special cases of the confirmed order can be written as follows:<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">@Test&lt;br&gt;\npublic void testConfirmOrder_Open() {&lt;br&gt;\n    fixture.given(new OrderCreatedEvent(&quot;Chair1&quot;))&lt;br&gt;\n            .when(new ConfirmOrderCommand(fixture.getAggregateIdentifier().asString()))&lt;br&gt;\n            .expectEvents(new OrderConfirmedEvent());&lt;br&gt;\n}&lt;\/p&gt;\n&lt;p&gt;@Test&lt;br&gt;\npublic void testConfirmOrder_WasAlreadyCancelled() {&lt;br&gt;\n    fixture.given(new OrderCreatedEvent(&quot;Chair1&quot;), new OrderCancelledEvent())&lt;br&gt;\n            .when(new ConfirmOrderCommand(fixture.getAggregateIdentifier().asString()))&lt;br&gt;\n            .expectEvents();&lt;br&gt;\n}&lt;br&gt;\n<\/pre><\/p>\n<p>When you run these tests, they will fail: The aggregate [Order] does not have a suitable constructor. But just before we move to the Order aggregate, let\u2019s fix the OrderCommandHandler. We need to be able to inject a Repository&lt;Order&gt; in it. Let\u2019s create a field and a setter to inject them.<\/p>\n<p>Next, we need a method to accept each type of command. Each of these three methods needs to be annotated with @CommandHandler, to tell Axon it should receive commands. Here is some code for two of the command handlers (the third is quite similar to the second one):<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">@CommandHandler&lt;br&gt;\npublic void createOrder(CreateOrderCommand command) {&lt;br&gt;\n    orderRepository.add(new Order(command.getOrderId(), command.getProductId()));&lt;br&gt;\n}&lt;\/p&gt;\n&lt;p&gt;@CommandHandler&lt;br&gt;\npublic void confirmOrder(ConfirmOrderCommand command) {&lt;br&gt;\n    Order order = orderRepository.load(new StringAggregateIdentifier(command.getOrderId()));&lt;br&gt;\n    order.confirm();&lt;br&gt;\n}<\/pre><\/p>\n<p>Note that we don&#8217;t need to do any &#8220;save&#8221; or &#8220;commit&#8221; operation on the repository. Axon takes care of that for you. In this example, the commands return the orderId as a String, which is wrapped in a StringAggregateIdentifier. You could also pass around the AggregateIdentifier instance itself. Whatever you like most.<\/p>\n<p>Now we\u2019re ready to go to the core of the command handling component: the Order aggregate. Since we\u2019ve decided to use event sourcing, we need to create an Order class and make it extend AbstractAnnotatedAggregateRoot.<\/p>\n<p>Let\u2019s start with the constructor. It should do two things: call the super constructor with an explicit aggregate identifier to force our own identifier on the instance, and initialize the Order\u2019s status to \u201cOpen\u201d.<\/p>\n<p>Here is what the constructor would look like:<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">public Order(String orderId, String productId) {&lt;br&gt;\n    super(new StringAggregateIdentifier(orderId));&lt;br&gt;\n    this.status = Status.OPEN; \/\/ just an enum with OPEN, CANCELLED and CONFIRMED&lt;br&gt;\n}<\/pre><\/p>\n<p>But that\u2019s not really event sourcing! State changes should be the result of an event. In Axon, it\u2019s easy to convert this constructor to a truly event sourced one. Here\u2019s how:<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">public Order(String orderId, String productId) {&lt;br&gt;\n    super(new StringAggregateIdentifier(orderId));&lt;br&gt;\n    apply(new OrderCreatedEvent(productId));&lt;br&gt;\n}&lt;\/p&gt;\n&lt;p&gt;@EventHandler&lt;br&gt;\nprivate void onCreate(OrderCreatedEvent event) {&lt;br&gt;\n    status = Status.OPEN;&lt;br&gt;\n    productId = event.getProductId();&lt;br&gt;\n}&lt;br&gt;\n<\/pre><\/p>\n<p>The apply method will record the event and keep it prepared for publishing, but also invokes the correct event handler method inside the aggregate itself. The latter is reponsible for applying the actual state changes involved with the creation of a new Order.<\/p>\n<p>The code for confirming an order is build up in a similar fashion. The confirm() method does the validation, the event handler does the state changes<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">public void confirm() {&lt;br&gt;\n\/\/ we can only confirm an open order.&lt;br&gt;\n    if (status == Status.OPEN) {&lt;br&gt;\n        apply(new OrderConfirmedEvent());&lt;br&gt;\n    }&lt;br&gt;\n}&lt;\/p&gt;\n&lt;p&gt;@EventHandler&lt;br&gt;\nprivate void onConfirm(OrderConfirmedEvent event) {&lt;br&gt;\n    status = Status.CONFIRMED;&lt;br&gt;\n}<\/pre><\/p>\n<p>We&#8217;re almost done. If you run the test, you&#8217;ll notice that the error still appears. That&#8217;s because Axon&#8217;s Generic repository expects the aggregate to have a special constructor: one that only accepts an AggregateIdentifier. So, just add that constructor and simply make it call the superconstructor with the same parameters. Now run the tests again. They should all pass.<\/p>\n<p>Everything works in the test fixture. But to get things working in production too, you need to add the @Component annotation (by Spring) to your command handler and add two beans to your Spring application context:<\/p>\n<p><pre class=\"brush: xml; title: ; notranslate\" title=\"\">&amp;lt;axon:event-sourcing-repository id=&quot;orderRepository&quot; aggregate-type=&quot;com.acme.oms.commandhandling.Order&quot; \/&amp;gt;&lt;br&gt;\n&amp;lt;axon:jpa-event-store id=&quot;eventStore&quot; \/&amp;gt;&lt;br&gt;\n<\/pre><\/p>\n<h2>Step 4 \u2013 Query component<\/h2>\n<p>In the tutorial, let&#8217;s keep the event query component simple. Let&#8217;s &#8220;write&#8221; all the events to the System.out first. I assume that you know how to insert data into a database and read it back out. <\/p>\n<p>The most important component in the query component is the event handlers. With Axon, creating a query component is really simple. Just create a class, make it a Spring bean by adding the @Component annotation and add methods that handle events.<\/p>\n<p>Here is example:<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">@Component&lt;br&gt;\npublic class OrderEventHandler {&lt;\/p&gt;\n&lt;p&gt;    @EventHandler&lt;br&gt;\n    public void handleOrderCreated(OrderCreatedEvent event) {&lt;br&gt;\n        System.out.println(String.format(&quot;An order is created: &#x5B;%s] for product: &#x5B;%s]&quot;,&lt;br&gt;\n                                         event.getOrderId(),&lt;br&gt;\n                                         event.getProductId()));&lt;br&gt;\n    }&lt;\/p&gt;\n&lt;p&gt;    @EventHandler&lt;br&gt;\n    public void handleOrderCancelled(OrderCancelledEvent event) {&lt;br&gt;\n        System.out.println(String.format(&quot;An order is cancelled: &#x5B;%s]&quot;, event.getOrderId()));&lt;br&gt;\n    }&lt;\/p&gt;\n&lt;p&gt;    @EventHandler&lt;br&gt;\n    public void handleOrderConfirmed(OrderConfirmedEvent event) {&lt;br&gt;\n        System.out.println(String.format(&quot;An order is confirmed: &#x5B;%s]&quot;, event.getOrderId()));&lt;br&gt;\n    }&lt;br&gt;\n}<\/pre><\/p>\n<p>That&#8217;s it! Axon&#8217;s annotation config together with Spring&#8217;s classpath scanning will automatically find this class and register it with the event bus as an event listener. Just create a simple Runner class with a main method to start the Spring context and fire some commands at the command bus. Or, just download the tutorial code and run the Runner class.<\/p>\n<h2>Conclusion<\/h2>\n<p>It is some wiring to get started. But once that\u2019s all in place you&#8217;re good to go for quite a while. Adding command handlers or event handlers is just a matter of creating a class and annotating the methods on them.<\/p>\n<p>To find out more about the Axon Framework, visit <a href=\"http:\/\/www.axonframework.org\">www.axonframework.org<\/a>. From there, you can download the binaries and documentation in case you need some help on the advanced topics.<\/p>\n<p>Enjoy.<\/p>\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/bit.ly\/3BAo305\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"256\" src=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\" alt=\"\" class=\"wp-image-20303\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png 1024w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-300x75.png 300w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-768x192.png 768w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1536x384.png 1536w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-2048x512.png 2048w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1920x480.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Axon Framework greatly simplifies building CQRS based Event Driven architectures in Java. Such an architecture provides very powerful options in terms of application scalability and extensibility. In this tutorial, I want to go though the process of setting up a basic application architecture with the Axon Framework.<\/p>\n","protected":false},"author":14,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":""},"categories":[81,98,10],"tags":[80,46],"class_list":["post-2608","post","type-post","status-publish","format-standard","hentry","category-axon-framework","category-microservices","category-development","tag-axon-framework","tag-cqrs"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Tutorial - Getting started with CQRS and Axon Framework - Trifork Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Tutorial - Getting started with CQRS and Axon Framework - Trifork Blog\" \/>\n<meta property=\"og:description\" content=\"Axon Framework greatly simplifies building CQRS based Event Driven architectures in Java. Such an architecture provides very powerful options in terms of application scalability and extensibility. In this tutorial, I want to go though the process of setting up a basic application architecture with the Axon Framework.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/\" \/>\n<meta property=\"og:site_name\" content=\"Trifork Blog\" \/>\n<meta property=\"article:published_time\" content=\"2010-11-12T17:34:57+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\" \/>\n<meta name=\"author\" content=\"Allard Buijze\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Allard Buijze\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/\",\"url\":\"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/\",\"name\":\"Tutorial - Getting started with CQRS and Axon Framework - Trifork Blog\",\"isPartOf\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\",\"datePublished\":\"2010-11-12T17:34:57+00:00\",\"author\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/a4e232a11dc57a2c4c581956ce6fde63\"},\"breadcrumb\":{\"@id\":\"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/#primaryimage\",\"url\":\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\",\"contentUrl\":\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/trifork.nl\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tutorial &#8211; Getting started with CQRS and Axon Framework\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/trifork.nl\/blog\/#website\",\"url\":\"https:\/\/trifork.nl\/blog\/\",\"name\":\"Trifork Blog\",\"description\":\"Keep updated on the technical solutions Trifork is working on!\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/trifork.nl\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/a4e232a11dc57a2c4c581956ce6fde63\",\"name\":\"Allard Buijze\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/3e7130b2465615e105b1addd400a3f06?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/3e7130b2465615e105b1addd400a3f06?s=96&d=mm&r=g\",\"caption\":\"Allard Buijze\"},\"description\":\"Allard (@allardbz) is CTO of Trifork Amsterdam and founder of Axon Framework. He is a trainer and speaker at conferences on topics related to scalable architecture and domain driven design. He strongly believes that good craftsmanship can only be achieved through continuous and intensive exchange of experience with others. The last years, he has been investigating and applying CQRS to a number of projects. As a result, he created the Axon Framework, an open source Java framework that helps developers create scalable and extensible applications. Axon has a growing community and has already been successfully introduced in several high-profile projects around the world.\",\"url\":\"https:\/\/trifork.nl\/blog\/author\/allard\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Tutorial - Getting started with CQRS and Axon Framework - Trifork Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/","og_locale":"en_US","og_type":"article","og_title":"Tutorial - Getting started with CQRS and Axon Framework - Trifork Blog","og_description":"Axon Framework greatly simplifies building CQRS based Event Driven architectures in Java. Such an architecture provides very powerful options in terms of application scalability and extensibility. In this tutorial, I want to go though the process of setting up a basic application architecture with the Axon Framework.","og_url":"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/","og_site_name":"Trifork Blog","article_published_time":"2010-11-12T17:34:57+00:00","og_image":[{"url":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png","type":"","width":"","height":""}],"author":"Allard Buijze","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Allard Buijze","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/","url":"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/","name":"Tutorial - Getting started with CQRS and Axon Framework - Trifork Blog","isPartOf":{"@id":"https:\/\/trifork.nl\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/#primaryimage"},"image":{"@id":"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/#primaryimage"},"thumbnailUrl":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png","datePublished":"2010-11-12T17:34:57+00:00","author":{"@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/a4e232a11dc57a2c4c581956ce6fde63"},"breadcrumb":{"@id":"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/#primaryimage","url":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png","contentUrl":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png"},{"@type":"BreadcrumbList","@id":"https:\/\/trifork.nl\/blog\/tutorial-getting-started-with-cqrs-and-axon-framework\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/trifork.nl\/blog\/"},{"@type":"ListItem","position":2,"name":"Tutorial &#8211; Getting started with CQRS and Axon Framework"}]},{"@type":"WebSite","@id":"https:\/\/trifork.nl\/blog\/#website","url":"https:\/\/trifork.nl\/blog\/","name":"Trifork Blog","description":"Keep updated on the technical solutions Trifork is working on!","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/trifork.nl\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/a4e232a11dc57a2c4c581956ce6fde63","name":"Allard Buijze","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/3e7130b2465615e105b1addd400a3f06?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/3e7130b2465615e105b1addd400a3f06?s=96&d=mm&r=g","caption":"Allard Buijze"},"description":"Allard (@allardbz) is CTO of Trifork Amsterdam and founder of Axon Framework. He is a trainer and speaker at conferences on topics related to scalable architecture and domain driven design. He strongly believes that good craftsmanship can only be achieved through continuous and intensive exchange of experience with others. The last years, he has been investigating and applying CQRS to a number of projects. As a result, he created the Axon Framework, an open source Java framework that helps developers create scalable and extensible applications. Axon has a growing community and has already been successfully introduced in several high-profile projects around the world.","url":"https:\/\/trifork.nl\/blog\/author\/allard\/"}]}},"_links":{"self":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/2608","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/users\/14"}],"replies":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/comments?post=2608"}],"version-history":[{"count":0,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/2608\/revisions"}],"wp:attachment":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/media?parent=2608"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/categories?post=2608"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/tags?post=2608"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}