In the end, we need to implement the Invoker, the bridge component between the standard application and the RECQ architecture.
An Invoker is a class annotated with @Invoker (com.evento.common.modeling.annotations.component.Invoker) and extending the com.evento.application.proxy.InvokerWrapper class. An invoker contains methods annotated with @InvocationHandler (com.evento.common.modeling.annotations.handler.InvocationHandler) used to implement business logic using the Command Gateway and the Query Gateway that you can access with getCommandGateway() and getQueryGateway() methods.
import com.eventoframework.demo.todo.api.todo.command.*;
import com.eventoframework.demo.todo.api.todo.query.TodoListListItemViewSearchQuery;
import com.eventoframework.demo.todo.api.todo.query.TodoListViewFindByIdentifierQuery;
import com.eventoframework.demo.todo.api.todo.view.TodoListListItemView;
import com.eventoframework.demo.todo.api.todo.view.TodoListView;
import com.evento.application.proxy.InvokerWrapper;
import com.evento.common.modeling.annotations.component.Invoker;
import com.evento.common.modeling.annotations.handler.InvocationHandler;
import com.evento.common.modeling.messaging.message.application.Metadata;
import com.evento.common.modeling.messaging.query.Multiple;
import com.evento.common.modeling.messaging.query.Single;
import java.util.Collection;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@Invoker
public class TodoListInvoker extends InvokerWrapper {
@InvocationHandler
public String createTodoList(String name, String user){
var identifier = "TDLS_" + UUID.randomUUID();
getCommandGateway().sendAndWait(new TodoListCreateCommand(identifier, name), toUserMetadata(user));
return identifier;
}
@InvocationHandler
public void deleteTodoList(String identifier, String user){
getCommandGateway().sendAndWait(new TodoListDeleteCommand(identifier), toUserMetadata(user));
}
@InvocationHandler
public String addTodo(String identifier, String content, String user){
var todoIdentifier = "TODO_" + UUID.randomUUID();
getCommandGateway().sendAndWait(new TodoListAddTodoCommand(identifier, todoIdentifier, content), toUserMetadata(user));
return todoIdentifier;
}
@InvocationHandler
public void checkTodo(String identifier, String todoIdentifier, String user){
getCommandGateway().sendAndWait(new TodoListCheckTodoCommand(identifier, todoIdentifier), toUserMetadata(user));
}
@InvocationHandler
public void removeTodo(String identifier, String todoIdentifier, String user){
getCommandGateway().sendAndWait(new TodoListRemoveTodoCommand(identifier, todoIdentifier), toUserMetadata(user));
}
@InvocationHandler
public CompletableFuture<TodoListView> findTodoListByIdentifier(String identifier){
return getQueryGateway().query(new TodoListViewFindByIdentifierQuery(identifier)).thenApply(Single::getData);
}
@InvocationHandler
public CompletableFuture<Collection<TodoListListItemView>> searchTodoList(String nameLike, int page){
return getQueryGateway().query(new TodoListListItemViewSearchQuery(nameLike, page, 15))
.thenApply(Multiple::getData);
}
private Metadata toUserMetadata(String user) {
var m = new Metadata();
m.put("user", user);
return m;
}
}
An invoker implements the Service Layer of the Layered Architecture, also, this separation gives the correct level of abstraction when you need to interact with other java frameworks or libraries.