Evento Framework
  • Introduction
  • Architecture Overview
    • Distributed Systems & Microservices
    • Recative Manifesto & Reactive Principles
    • State-of-the-art Patterns
      • DDD (Domain Driven Design)
      • CQRS (Command Query Responsability Separation)
      • Event Sourcing
      • Messaging
      • Saga
  • GETTING STARTED
    • Quick Start
    • TodoList - RECQ Tutorial
      • Problem Description and Requirement Gathering
      • RECQ Payload Design
      • RECQ Components Design
      • Set up your Development Environment
      • RECQ Payload Evento Implementation
        • Domain Commands
        • Domain Events
        • Views
        • Queries
      • RECQ Components Evento Implementation with Spring Data
        • TodoListAggregate
        • TodoList Model with Spring Data
        • TodoListProjector
        • TodoListProjection
        • TodoList Invoker
      • Expose the RECQ architecture with Spring Web
      • Test Your App
    • Extend TodoList - Handle Complexity Tutorial
      • Unique identifier generation
      • Extends behaviors with Observer and Services
      • Cross Domain Consistency with Sagas
      • Handle Real time data updates with MQTT and Save-Notify Pattern
  • RECQ Patterns
    • RECQ Patterns
    • RECQ System Pattern
      • Component
      • Message Gateway
      • System State Store
    • RECQ Communication Pattern
      • Component to Component
      • Component to System State Store
      • System State Store to Component
    • RECQ Component Pattern
      • Aggregate
      • Projector
      • Projection
      • Service
      • Invoker
      • Saga
      • Observer
  • Evento Framework
    • Evento Framework Introcution
    • Payload and Messages
      • Command
        • Domain Command
        • Service Command
      • Event
        • Domain and Service Event
      • Query and View
    • @Component
      • @Aggregate
        • Aggregate State
        • @AggregateCommandHandler
        • @EventSourcingHandler
      • @Projector
        • Projector @EventHandler
      • @Projection
        • @QueryHandler
      • @Service
        • @CommandHandler
      • @Invoker
      • @Saga
        • SagaState
        • @SagaEventHandler
      • @Observer
    • Dead Event Queues
    • EventoBundle
      • EventoServerMessageBusConfiguration
      • ConsumerStateStore
        • InMemoryConsumerStateStore
        • PostgresConsumerStateStore
        • MysqlConsumerStateStore
      • Context
      • TracingAgend and @Track
        • SentryTracingAgent
      • Autoscaling Protocol
        • ThreadCountAutoscalingProtocol
      • Injector and @Component
  • Evento Server
    • Evento Server Introduction
    • SetUp Evento Server
      • Advanced Options
      • Evento Event Store Modes: APES and CPES
    • Evento Server Cluster
    • Bundle Deploy Script
  • EVENTO GUI
    • Explore RECQ Systems Visually
    • GUI Auth
    • Payload Catalog
    • Component Catalog
    • Bundle Catalog
    • Cluster Status (Experimental)
    • Flows
      • Performance Evaluation
    • Application Graph
    • System State Store
  • Evento CLI
    • Evento CLI Introduction
    • Update Version
    • Publish
Powered by GitBook
On this page
  1. GETTING STARTED
  2. TodoList - RECQ Tutorial
  3. RECQ Components Evento Implementation with Spring Data

TodoListProjector

PreviousTodoList Model with Spring DataNextTodoListProjection

Last updated 1 year ago

After the proper definition of the Event Generation in our System and the Model/Repository Layers, we can start to build our Projector, also known as, the domain materializer. The main goal of this component is to store in a database a particular View of the System State.

In Evento Framework a Projector is a simple class annotated with @Projector (com.evento.common.modeling.annotations.component.Projector). This annotation requires a parameter called version that indicate the materialization version in order to recreate the database or change the structure. A complete description of a projector can be found in the .

import com.evento.common.modeling.messaging.message.application.Metadata;
import com.eventoframework.demo.todo.api.todo.event.*;
import com.eventoframework.demo.todo.query.model.Todo;
import com.eventoframework.demo.todo.query.model.TodoList;
import com.eventoframework.demo.todo.query.model.TodoListRepository;
import com.evento.common.modeling.annotations.component.Projector;
import com.evento.common.modeling.annotations.handler.EventHandler;
import com.evento.common.modeling.messaging.message.application.EventMessage;

import java.time.Instant;
import java.time.ZoneId;
import java.util.ArrayList;

@Projector(version = 1)
public class TodoListProjector{

    private final TodoListRepository repository;


    public TodoListProjector(TodoListRepository repository) {
        this.repository = repository;
    }

    @EventHandler
    public void on(TodoListCreatedEvent event, Metadata metadata, Instant timestamp) {
        repository.save(new TodoList(
                event.getIdentifier(),
                event.getContent(),
                metadata.get("user"),
                null,
                timestamp.atZone(ZoneId.systemDefault()),
                null,
                new ArrayList<>()
        ));
    }

    @EventHandler
    public void on(TodoListDeletedEvent event, EventMessage<TodoListCreatedEvent> message) {
        repository.delete(repository.findById(event.getIdentifier()).orElseThrow());
    }

    @EventHandler
    public void on(TodoListTodoAddedEvent event, Metadata metadata, Instant timestamp) {
        var list = repository.findById(event.getIdentifier()).orElseThrow();
        var td = new Todo(
                event.getTodoIdentifier(),
                event.getContent(),
                metadata.get("user"),
                null,
                timestamp.atZone(ZoneId.systemDefault()),
                null
        );
        list.getTodos().add(td);
        list.setUpdatedAt(td.getCreatedAt());
        list.setUpdatedBy(td.getCreatedBy());
        repository.save(list);
    }

    @EventHandler
    public void on(TodoListTodoRemovedEvent event, Metadata metadata, Instant timestamp) {
        var list = repository.findById(event.getIdentifier()).orElseThrow();
        list.getTodos().removeIf(t -> event.getTodoIdentifier().equals(t.getIdentifier()));
        list.setUpdatedAt(timestamp.atZone(ZoneId.systemDefault()));
        list.setUpdatedBy(metadata.get("user"));
        repository.save(list);
    }

    @EventHandler
    public void on(TodoListTodoCheckedEvent event, Metadata metadata, Instant timestamp) {
        var list = repository.findById(event.getIdentifier()).orElseThrow();
        var td = list.getTodos().stream().filter(t -> event.getTodoIdentifier().equals(t.getIdentifier())).findFirst().orElseThrow();
        td.setCompletedAt(timestamp.atZone(ZoneId.systemDefault()));
        td.setCompletedBy(metadata.get("user"));
        list.setUpdatedAt(td.getCompletedAt());
        list.setUpdatedBy(td.getCompletedBy());
        repository.save(list);
    }
}
Projector Chapter