The Evento Framework empowers you to build robust and scalable applications with its well-defined approach to handling queries. This section delves into the core concepts of Query Payloads and Messages, providing the foundation for effective data retrieval within your Evento applications.
By leveraging these concepts, you can design a clear separation between your queries and their corresponding response structures. This improves code readability, and maintainability, and promotes a consistent communication pattern within your microservices architecture.
Source Code Breakdown
The following code snippets showcase the key Evento classes involved in query handling:
1. Query Class (Query.java):
/** * The Query class is an abstract class that represents a query object. It extends the TrackablePayload class. * It is generic, with a type parameter T that must extend the QueryResponse class. * * @param <T> The type of the response object that the Query returns. * * @see TrackablePayload * @see QueryResponse */publicabstractclassQuery<TextendsQueryResponse<?>> extendsTrackablePayload { /** * Returns the response type of the Query. * * @return The Class object representing the response type. */ @SuppressWarnings("unchecked")publicClass<T> getResponseType() {return (Class<T>) ((ParameterizedType) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]).getRawType(); }}
The Query class establishes the foundation for building queries. It enforces the TrackablePayload class, indicating that queries carry data. The generic type parameter T allows you to specify the expected response type (QueryResponse). The getResponseType() method leverages generics to determine the Class object representing the expected response data structure.
2. QueryMessage (QueryMessage.java):
importcom.evento.common.modeling.messaging.payload.Query;/** * The QueryMessage class represents a message containing a query. * * @param <T> The type of the query payload. */publicclassQueryMessage<TextendsQuery<?>> extendsMessage<T> { /** * The QueryMessage class represents a message containing a query. * * @param payload The Query payload */publicQueryMessage(T payload) { super(payload); } /** * The QueryMessage class represents a message containing a query. * It is a subclass of the Message class and is generically typed with a Query payload. * The QueryMessage class provides methods to retrieve the query name and query payload. * */publicQueryMessage() { } /** * Retrieves the name of the query. * * @return The name of the query as a String. */publicStringgetQueryName() {return super.getPayloadName(); }}
The QueryMessage class acts as a container for Query objects. It inherits from the Message class, providing functionalities for message routing and handling. Additionally, it retrieves the query name from the underlying payload (if it has a name).
3. QueryResponse (QueryResponse.java):
import com.evento.common.modeling.messaging.payload.View;import java.io.Serializable;/** * The QueryResponse class is an abstract class that represents a response object for a query. * It is Serializable, which means it can be converted into a byte stream and sent over a network or stored in a file. * The class is generic, with a type parameter T that must extend the View class. * It provides methods to set and retrieve the data from the response. * * @param <T> The type of view the QueryResponse object contains. */public abstract class QueryResponse<T extends View> implements Serializable {}
importcom.evento.common.modeling.messaging.payload.View;/** * Creates a new instance of the Single class. * @param <T> the view response of a query */publicclassSingle<TextendsView> extendsQueryResponse<T> {privateT data; /** * The Single class represents a response containing a single view object. * It extends the QueryResponse class. * <p> * This class is generic and the type parameter T must extend the View class. * It provides methods to set and retrieve the data from the response. */publicSingle() { } /** * Creates a new Single object with the given data. * * @param <R> the type of the data in the response, must extend the View class * @param data the data to set in the response * @return the Single object with the provided data */publicstatic <RextendsView> Single<R> of(R data) {var r =newSingle<R>();r.setData(data);return r; } /** * Retrieves the data stored in the response object. * * @return the data stored in the response object */publicTgetData() {return data; } /** * Sets the data in the response object. * * @param data the data to be set in the response object. It must extend the View class. */publicvoidsetData(T data) {this.data= data; }}
importcom.evento.common.modeling.messaging.payload.View;importjava.util.ArrayList;importjava.util.Collection;importjava.util.List;/** * Represents a response object that contains multiple instances of a specified type. * Extends the `QueryResponse` class. * * @param <T> The type of view the Multiple object contains. */publicclassMultiple<TextendsView> extendsQueryResponse<T> {privateCollection<T> data; /** * Represents a response object that contains multiple instances of a specified type. * Extends the `QueryResponse` class. * */publicMultiple() { } /** * Constructs a new Multiple object containing multiple instances of a specified type. * * @param <R> The type of view the Multiple object contains. * @param data The collection of views to be contained in the Multiple object. * @return A new Multiple object containing the specified views. */publicstatic <RextendsView> Multiple<R> of(Collection<R> data) {var r =newMultiple<R>();r.setData(newArrayList<>(data));return r; } /** * Constructs a new Multiple object containing multiple instances of a specified type. * * @param <R> The type of view the Multiple object contains. * @param items The array of views to be contained in the Multiple object. * @return A new Multiple object containing the specified views. */ @SafeVarargspublicstatic <RextendsView> Multiple<R> of(R... items) {var r =newMultiple<R>();r.setData(List.of(items));return r; } /** * Retrieves the data contained in the Multiple object. * * @return The collection of views contained in the Multiple object. */publicCollection<T> getData() {return data; } /** * Sets the data for the Multiple object. * * @param data The collection of views to be set as the data for the Multiple object. */publicvoidsetData(Collection<T> data) {this.data= data; }}
The QueryResponse class serves as an abstract base class for all query response objects. It enforces data serialization by implementing Serializable. The generic type parameter T restricts the response data type to extend the View interface (discussed later). Concrete implementations like Single<T> and Multiple<T> cater to different response scenarios:
Single<T>: Used for responses containing a single View object.
Multiple<T>: Used for responses containing a collection of View objects (e.g., list of todos).
4. View Interface (View.java):
/** * The View interface represents a view object that can be used in a software system. * It extends the Payload interface. */publicinterfaceViewextendsPayload {}
The View interface represents a simple data transfer object (DTO) used for transporting data within the Evento Framework. It extends the Payload interface, signifying it carries data. Views are essentially plain data structures that can be serialized for efficient network transmission.
Putting it Together:
By combining these components, you can design clear and well-defined queries along with their expected response structures. Here's an example demonstrating this concept:
Java
// Define a Query to retrieve all Todo itemspublicclassGetAllTodosQueryextendsQuery<Multiple<TodoView>> {// ... query logic}// Define a View for Todo datapublicclassTodoViewimplementsView {privateString id;privateString name;// ... other Todo properties// Getters and Setters}
In this example, the GetAllTodosQuery expects a response containing a collection of TodoView objects using the Multiple class. This structure clearly communicates the query's purpose and the format of the anticipated response.
By leveraging Evento's Query Payloads and Messages, you can create well-organized and maintainable applications that effectively handle data retrieval across your microservices architecture.