CQRS With Axon Tutorial: Part 5 – Build the Query Module

In this part, we would build the query module. This is in line with the CQRS principle: we separate the commands from the query.

We would cover the following:

  1. Build the API
  2. Create the DataProvider
  3. A Brief Review

 

1. Build the Query API

Follow the steps below:

Step 1: Add a kotlin file in the query package. Name it api. This file would hold the entity that would be stored in the database

Step 2: Annotate this class with the @Entity annotation

Step 3: Inside this file, create a data class with name CardSummary. The class will have the following parameters:

  • id of string? intialized to null
  • initialBalance of int? initialized to 0
  • remainingBalance also int? initialized to 0

Step 4: Add the @id annotation to the id variable

The content of the api.kt file is as given in the listing below:

 

@Entity
data class CardSummary(
        @Id var id: String? = null,
        var initialBalance: Int? = 0,
        var remainingBalance: Int? =0
)

 

2. Create the DataProvider

We would have to create a dataProvider in the GiftCardGUI class.This is required to create a projection that would be used in the grid.

Step 1: In the GiftCardGUI, create a final private variable of DataProvider (see code below)

Step 2: Do a constructor injection of a QueryGateway

At this point, the initial part of your GiftCardGUI would be the code listing below:

 

private final CommandGateway commandGateway;
private final DataProvider<CardSummary, Void> dataProvider;

public GiftCardGUI(CommandGateway commandGateway, QueryGateway queryGateway) {
    this.commandGateway = commandGateway;
    this.dataProvider = dataProvider(queryGateway);
}

 

Step 3: Place your cursor on the dataProvider(queryGateway) code which underlined with red squiggly lines.

Step 4: Choose ‘Create method dataProvider in GiftCardGUI’.

The method is create for you.

Step 5: Make this method return ‘new AbstractBackEndDataProvider. Make sure to use the intellisense to complete this statement.

You will see that two additional methods are added: fetchFromBackEnd() and sizeInBackEnd. We now need to implement these methods. Before write implement these method, we need to create a DataQuery and SizeQuery in the api.kt file

Step 6: Open the api.kt file (in the query module)

Step 7: Create a data class named DataQuery. This class should have two integer attributes offset and limit (see code below)

Step 8: Create another class (not data class) with name SizeQuery with no attributes.

The code for the two classes is shown below

 

data class DataQuery(val offset: Int, val limit: Int)
class SizeQuery

 

Now back to the GiftCardGUI

Step 9: Now implement the two methods. The complete implementation is given below:

 

private DataProvider<CardSummary, Void> dataProvider(QueryGateway queryGateway) {
    return new AbstractBackEndDataProvider<CardSummary, Void>() {
        @Override
        protected Stream<CardSummary> fetchFromBackEnd(Query<CardSummary, Void> query) {
            return queryGateway.query(new DataQuery(query.getOffset(), query.getLimit()),
                    ResponseTypes.multipleInstancesOf(CardSummary.class)
            ).join()
             .stream();
        }

        @Override
        protected int sizeInBackEnd(Query<CardSummary, Void> query) {
            return queryGateway.query(new SizeQuery(),
                    ResponseTypes.instanceOf(Integer.class))
                    .join();
        }
    };
}

 

3. A Brief Review

We started by creating the entity class that would represent  the data model (GiftCard)

Then we added a DataProvider variable to the GiftCardGUI

Then we did a construction injection of the DataProvider into the class

We then went to the api file and added DataQuery data class and a SizeQuery class

Finally we implemented the dataProvider method which returns a AbstractBackEndDataProvider object in which implemented the two required methods FetchFromBackEnd() and SizeInBackEnd().

 

In the next part, we would then create the summaryProjection.

Remember you can download the complete code from my github repository.