Expose the RECQ architecture with Spring Web

The last level of the layered architecture after the service, implemented by a RECQ Invoker, is the Controller.

The main goal of a controller is let user interact with the software core logic using a particular protocol or interface.

In this tutorial, we are going to expose our System with a REST Interface implemented by a Spring Controller.

import com.eventoframework.demo.todo.api.todo.view.TodoListListItemView;
import com.eventoframework.demo.todo.api.todo.view.TodoListView;
import com.eventoframework.demo.todo.service.invoker.TodoListInvoker;
import com.evento.application.EventoBundle;
import com.eventoframework.demo.todo.web.dto.CreatedResponse;
import com.eventoframework.demo.todo.web.dto.TodoCreateRequest;
import com.eventoframework.demo.todo.web.dto.TodoListCreateRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;
import java.util.concurrent.CompletableFuture;

@RestController
@RequestMapping("/todo-list")
public class TodoListController {

    private final TodoListInvoker todoListInvoker;

    public TodoListController(EventoBundle eventoBundle) {
        // Instantiate the invoker
        todoListInvoker = eventoBundle.getInvoker(TodoListInvoker.class);
    }

    @GetMapping("/")
    public CompletableFuture<ResponseEntity<Collection<TodoListListItemView>>> searchTodoList(
           @RequestParam(defaultValue = "") String nameLike, @RequestParam(defaultValue = "0") int page
    ) {
        return todoListInvoker
                .searchTodoList(nameLike, page)
                .thenApply(ResponseEntity::ok);
    }

    @GetMapping("/{identifier}")
    public CompletableFuture<ResponseEntity<TodoListView>> findTodoListByIdentifier(
            @PathVariable String identifier) {
        return todoListInvoker
                .findTodoListByIdentifier(identifier)
                .thenApply(ResponseEntity::ok);
    }

    @PostMapping("/")
    public ResponseEntity<CreatedResponse> createTodoList(
            @RequestBody TodoListCreateRequest request, @RequestHeader(name = "Authorization") String user) {
        return ResponseEntity
                .status(HttpStatus.CREATED)
                .body(new CreatedResponse(
                        todoListInvoker.createTodoList(request.getName(), user)
                ));
    }


    @DeleteMapping("/{identifier}")
    public ResponseEntity<Void> deleteTodoList(
            @PathVariable String identifier,
            @RequestHeader(name = "Authorization") String user) {
        todoListInvoker.deleteTodoList(identifier, user);
        return ResponseEntity.noContent().build();
    }

    @PostMapping("/{identifier}/todo/")
    public ResponseEntity<CreatedResponse> addTodo(
            @PathVariable String identifier,
            @RequestBody TodoCreateRequest request,
            @RequestHeader(name = "Authorization") String user) {
        return ResponseEntity.status(HttpStatus.CREATED)
                .body(new CreatedResponse(
                        todoListInvoker.addTodo(identifier, request.getContent(), user)
                ));
    }

    @DeleteMapping("/{identifier}/todo/{todoIdentifier}")
    public ResponseEntity<Void> removeTodo(
            @PathVariable String identifier,
            @PathVariable String todoIdentifier,
            @RequestHeader(name = "Authorization") String user) {
        todoListInvoker.removeTodo(identifier, todoIdentifier, user);
        return ResponseEntity.noContent().build();
    }

    @PutMapping("/{identifier}/todo/{todoIdentifier}")
    public ResponseEntity<Void> checkTodo(
            @PathVariable String identifier,
            @PathVariable String todoIdentifier,
            @RequestHeader(name = "Authorization") String user) {
        todoListInvoker.checkTodo(identifier, todoIdentifier, user);
        return ResponseEntity.accepted().build();
    }
}

DTOs

import lombok.Data;

@Data
public class TodoListCreateRequest {
    private String name;
}
import lombok.Data;

@Data
public class TodoCreateRequest {
    private String content;
}
import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class CreatedResponse {
    private String identifier;
}

Last updated