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 12 months 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