Table Updaters
Table Updaters are the core components that define and maintain view tables. They subscribe to events or state changes from entities and transform this data into queryable views. This page explains how to define and use Table Updaters in your View components.
What are Table Updaters?
A Table Updater is a Java class defined inside your View that:
-
Specifies a data source (entity or topic)
-
Defines the structure of a view table
-
Contains logic for transforming incoming data into view rows
-
Handles updates, deletes, and other operations on the view table
Basic Structure
A Table Updater is defined as a static inner class inside your View:
@ComponentId("customer-view")
public class CustomerView extends View {
@Table("customers") // Optional table name
@Consume.FromKeyValueEntity(CustomerEntity.class)
public static class Customers extends TableUpdater<Customer> {
// Transformation methods go here
}
// Query methods go here
}
For a full view sample see Creating a View from a Key Value Entity
Table Naming
Table names can be specified explicitly with the @Table
annotation:
@Table("customers")
public static class Customers extends TableUpdater<Customer> { }
For single table views the annotation is optional and is derived from the table name used in the queries in the view.
For multi table Advanced Views each updater must have the annotation to specify which table name it updates.
Data Sources
Table Updaters can consume data from different sources:
Key Value Entities
Subscribe to state changes from Key Value Entities:
@Consume.FromKeyValueEntity(CustomerEntity.class)
For a full sample see Creating a View from a Key Value Entity
Event Sourced Entities
Subscribe to events from Event Sourced Entities:
@Consume.FromEventSourcedEntity(CustomerEntity.class)
For a full sample see Creating a View from an Event Sourced Entity
Workflows
Subscribe to state changes from Workflows:
@Consume.FromWorkflow(TransferWorkflow.class)
For a full sample see Creating a View from a Workflow
Service to service eventing
Subscribe to events from an Event Sourced entity made available by another Akka service:
@Consume.FromServiceStream("service-name", "stream-id")
For more details see Service to Service Eventing
Topics
Subscribe to messages from a topic:
@Consume.FromTopic("customer-events")
For a full sample see Creating a View from a topic
Generic Type Parameter
The generic type parameter of TableUpdater<T>
defines the structure of each row in the view table:
public static class Customers extends TableUpdater<Customer> { }
This means each row in the view table will have the structure of the Customer
class.
Transformation Methods
Table Updaters can include an onUpdate
method to transform incoming data. The update method is handed the incoming event,
message or update, and returns an effect describing what should happen with the table row:
@Consume.FromKeyValueEntity(CustomerEntity.class)
public static class CustomerSummaries extends TableUpdater<CustomerSummary> {
public Effect<CustomerSummary> onUpdate(Customer customer) {
return effects().updateRow(
new CustomerSummary(
updateContext().eventSubject().get(),
customer.name(),
customer.email()
)
);
}
}
For a few examples of different table update handlers see Implementing Views
Effect Types
Table Updater methods return Effect
objects that define what happens to the view table:
Accessing Context
Table Updaters provide context about the current update:
Update Context
Access information about the event or state change:
// Get the entity ID
String entityId = updateContext().eventSubject().get();
// Check if the event originated in the local region
boolean isLocal = updateContext().hasLocalOrigin();
// Get the region where the event originated
String originRegion = updateContext().originRegion();
Row State
Access the current state of the row being updated:
// For immutable types, create a new instance with updated fields
return effects().updateRow(rowState().withName(nameChanged.newName()));
// For mutable types, modify and return
CustomerRow current = rowState();
current.setName(nameChanged.newName());
return effects().updateRow(current);
Multi-Table Views
A single View can define multiple Table Updaters to create a view with multiple tables:
@ComponentId("shop-view")
public class ShopView extends View {
@Table("customers")
@Consume.FromEventSourcedEntity(CustomerEntity.class)
public static class Customers extends TableUpdater<Customer> {
// Customer transformation methods
}
@Table("products")
@Consume.FromEventSourcedEntity(ProductEntity.class)
public static class Products extends TableUpdater<Product> {
// Product transformation methods
}
@Table("orders")
@Consume.FromKeyValueEntity(OrderEntity.class)
public static class Orders extends TableUpdater<Order> {
// Order transformation methods
}
// Query methods that can join across tables
@Query("""
SELECT c.name, o.*, p.name AS productName
FROM customers AS c
JOIN orders AS o ON c.id = o.customerId
JOIN products AS p ON o.productId = p.id
WHERE c.id = :customerId
""")
public QueryEffect<CustomerOrders> getCustomerOrders(String customerId) {
return queryResult();
}
}
For details on querying multi table views, see Advanced Views
Handling Deletes
To handle entity deletions
For Key Value Entities
Use the @DeleteHandler
annotation:
@Consume.FromKeyValueEntity(CustomerEntity.class)
public static class Customers extends TableUpdater<Customer> {
@DeleteHandler
public Effect<Customer> onDelete() {
return effects().deleteRow();
}
}
For Event Sourced Entities
Handle delete events explicitly:
@Consume.FromEventSourcedEntity(CustomerEntity.class)
public static class Customers extends TableUpdater<Customer> {
public Effect<Customer> onEvent(CustomerEvent event) {
return switch (event) {
case CustomerEvent.CustomerDeleted deleted -> effects().deleteRow();
// Handle other events
};
}
}
Related Features
-
Data Types - Types supported in views
-
FROM clause - Referencing tables in queries
-
JOIN clause - Combining data from multiple tables
-
Advanced Views - Creating complex views