In this part we would create the summary projection class.This class would be part of the query package.
This is would be a spring bean (annotated with @Component annotation) and would be responsible for handle persistence. So it would be able to saved data. Also, it should retrieve data from the database to be displayed on the grid in the GUI.
Follow the 14 steps given below:
Step 1: Create a java class in the query package. Name it SummaryProjection
Step 2: Annotate the class with the @Component annotation
Step 3: Add a final private variable of type EntityManager
Step 4: Add a constructor and inject the EntityManager variable
The code for step 3 and 4 is shown below
private final EntityManager entityManager; public SummaryProjection(EntityManager entityManager) { this.entityManager = entityManager; }
Step 5: Create event handlers for the IssuedEvent() and RedeemedEvent()
Step 6: Create Query handler to return a list of card summaries
Step 7: Create a Query handler for handling the SizeQuery
At this point, the four methods will be as shown below:
@EventHandler public void handle(IssuedEvent evt) { } @EventHandler public void handle(RedeemedEvent evt) { } @QueryHandler public List<CardSummary> handle(DataQuery query){ } @QueryHandler public Integer handle(SizeQuery query) { }
Step 8: For the IssuedEvent, you need to create and persist a new entity. The code is shown below:
entityManager.persist(new CardSummary( evt.getId(), evt.getAmount(), evt.getAmount() ));
Step 9: For the RedeemedEvent, you need to first find the CardSummary and then update it’s balance. The code is shown below
CardSummary summary = entityManager.find(CardSummary.class, evt.getId()); summary.setRemainingBalance(summary.getRemainingBalance() -evt.getAmount());
Step 10: Configure TrackingEventProcessor. You do this by creating an empty config method. It takes EventProcessingConfiguration as parameter.
Step 11: Annotate this method with @Autowired annotation
The code is given below:
//Configure Tracking Event @Autowired public void config(EventProcessingConfiguration config) { }
Step 12: For the List QueryHandler, you need to create a query that returns a List<CardSummary> using the create() query method of the entityManager. The code is given below:
return entityManager .createQuery("SELECT c FROM CardSummary c ORDER BY c.id", CardSummary.class) .getResultList();
Step 13: For the QueryHandler for SizeQuery, it would be similar to step 12. But this time write a query to return count..See code below
return entityManager .createQuery("SELECT COUNT(c) FROM CardSummary c", Long.class) .getSingleResult() .intValue();
At this point we are done with the summary projection and now we need to worry about getting the data into the grid in the GUI.
Step 14: Run the application. Also start the axonserver. Test to make sure everything works fine.
Just for review, I’m putting the complete code for the SummaryProjection class below. However, I recommend you type it out by yourself. In that way you improve your skills in CQRS with AxonFramework.
@Component public class SummaryProjection { private final EntityManager entityManager; public SummaryProjection(EntityManager entityManager) { this.entityManager = entityManager; } @EventHandler public void on(IssuedEvt evt) { entityManager.persist(new CardSummary( evt.getId(), evt.getAmount(), evt.getAmount() )); } @EventHandler public void on(RedeemedEvt evt) { CardSummary summary = entityManager.find(CardSummary.class, evt.getId()); summary.setRemainingBalance(summary.getRemainingBalance() - evt.getAmount()); } //Configuring tracking event processor @Autowired public void config(EventProcessingConfiguration config) { // config.eventProcessor(getClass().getPackage().getName()); } @QueryHandler public List<CardSummary> handle(DataQuery query) { return entityManager .createQuery("SELECT c FROM CardSummary c ORDER BY c.id", CardSummary.class) .getResultList(); } @QueryHandler public Integer handle(SizeQuery query) { return entityManager .createQuery("SELECT COUNT(c) FROM CardSummary c", Long.class) .getSingleResult() .intValue(); } }
