Skip to content

Annotations

Marks a data class as a Chronicle event type.

ParameterTypeDefaultDescription
idString""Stable identifier. Defaults to class name.
generationInt1Schema version. Increment when shape changes.
tombstoneBooleanfalseSignals event source retirement.
import io.cratis.chronicle.events.EventType
@EventType
data class OrderPlaced(val orderId: String, val totalAmount: Double)

Omitting id is the common case — Chronicle uses OrderPlaced as the identifier automatically.


Marks a class as a Chronicle reactor. Each public method becomes a handler for the event type of its first parameter.

ParameterTypeDefaultDescription
idString""Stable identifier. Defaults to class name.
eventSequenceStringevent logThe event sequence to observe. Overridden by @EventSequence.

A handler takes the event, and optionally an EventContext carrying the event’s metadata:

import io.cratis.chronicle.events.EventContext
import io.cratis.chronicle.observation.Reactor
@Reactor
class OrderNotifications {
fun orderPlaced(event: OrderPlaced) {
println("Order ${event.orderId} placed")
}
fun orderShipped(event: OrderShipped, context: EventContext) {
println("Order ${event.orderId} shipped at ${context.occurred}")
}
}

Supply an explicit id only when you need the identifier to survive class renames.


Excludes a reactor, or a single handler, from replay. Put it on the class and the whole reactor is registered as non-replayable, so redaction, revision, and observer rewind never replay it. Put it on one method and only that handler is skipped when an event arrives as part of a replay — the reactor’s other handlers still replay.

Use it for side effects where running again is worse than never running again.

import io.cratis.chronicle.observation.OnceOnly
import io.cratis.chronicle.observation.Reactor
@Reactor
class PaymentNotifications {
@OnceOnly
fun orderPlaced(event: OrderPlaced) {
println("Charging for ${event.orderId} - never repeated on replay")
}
}

Marks a reactor handler as the one to run while events are being replayed. When an event type has a handler marked with this, it takes over for the duration of the replay and the everyday handler does not also run. Without one, the everyday handler keeps running during replay.

Use @OnceOnly instead when the side effect should simply not happen again on replay.

import io.cratis.chronicle.observation.Reactor
import io.cratis.chronicle.observation.Replay
@Reactor
class ShippingNotifications {
fun orderPlaced(event: OrderPlaced) {
println("Emailing the customer about ${event.orderId}")
}
@Replay
fun orderPlacedDuringReplay(event: OrderPlaced) {
println("Rebuilding ${event.orderId} without emailing anyone")
}
}

Marks a class as a reducer. Each public method folds one event type into the read model.

ParameterTypeDefaultDescription
idString""Stable identifier. Defaults to class name.
eventSequenceStringevent logThe event sequence to observe. Overridden by @EventSequence.
isActiveBooleantrueWhether the kernel runs the reducer.

A handler takes the event, the state so far, and optionally an EventContext. The state is null until the first event for an event source has been folded in.

import io.cratis.chronicle.events.EventContext
import io.cratis.chronicle.observation.Reducer
@Reducer
class OrderSummaryReducer {
fun orderPlaced(event: OrderPlaced, state: OrderSummary?): OrderSummary =
(state ?: OrderSummary()).copy(orderId = event.orderId)
fun orderShipped(
event: OrderShipped,
state: OrderSummary?,
context: EventContext
): OrderSummary = (state ?: OrderSummary()).copy(status = "shipped at ${context.occurred}")
}

Marks a data class as a Chronicle read model.

ParameterTypeDefaultDescription
idString""Stable identifier. Defaults to class name.
displayNameString""Human-readable label. Defaults to name.
import io.cratis.chronicle.readModels.ReadModel
@ReadModel
data class OrderSummary(val orderId: String = "", val status: String = "pending")

Marks a class as a Chronicle projection, or overrides the projection identifier on a model-bound read model. It is optional — when omitted, the class simple name is used as the identifier.

For a declarative projection the read model type is inferred from the IProjectionFor<T> type parameter. For a model-bound projection the annotated class is itself the read model.

ParameterTypeDefaultDescription
idString""Stable identifier. Defaults to class name.
eventSequenceStringevent logThe event sequence to observe. Overridden by @EventSequence.
import io.cratis.chronicle.projections.FromEvent
import io.cratis.chronicle.projections.Projection
import io.cratis.chronicle.readModels.ReadModel
@ReadModel
@Projection(eventSequence = "outbox")
@FromEvent(OrderPlaced::class)
data class OutboxOrderTracking(val orderId: String = "")

Points an observer — a reactor, a reducer or a projection — at the event sequence it observes. This is the standalone alternative to the eventSequence parameter on @Reactor, @Reducer and @Projection; reach for it when the sequence is the only thing being configured, so the observer keeps its conventional identifier.

ParameterTypeDefaultDescription
valueString(required)The event sequence to observe.
import io.cratis.chronicle.observation.EventSequence
import io.cratis.chronicle.observation.Reactor
@Reactor
@EventSequence("outbox")
class OutboxOrderNotifications {
fun orderPlaced(event: OrderPlaced) {
println("Order ${event.orderId} placed, observed from the outbox")
}
}

When both this annotation and the eventSequence parameter are present, this annotation wins.

There is no @EventLog counterpart. In the .NET client it exists to override the inbox routing that [EventStore] on an event type turns on — and the Kotlin client has no @EventStore, so an observer without an explicit sequence already reads from the event log.


Marks a class as a Chronicle constraint definition. The class must implement IConstraint.

ParameterTypeDefaultDescription
idString""Stable identifier. Defaults to class name.

Marks a class as a Chronicle event seeder. The class must implement ICanSeedEvents.


Marks a property as personally identifiable information. Chronicle encrypts annotated fields at rest using a per-subject key. See PII Attribute for the full compliance model this participates in.

ParameterTypeDefaultDescription
descriptionString""Note about what the field holds.
import io.cratis.chronicle.compliance.Pii
import io.cratis.chronicle.events.EventType
@EventType
data class CustomerRegistered(
val customerId: String,
@Pii(description = "Customer email address") val email: String
)

Applied to a read model class to declare that its fields are mapped from an event type. Part of the annotation-based projection style. It is repeatable — apply it once per event type the read model projects from.

ParameterTypeDefaultDescription
eventTypeKClass<*>(required)The source event class.
keyString"EventSourceId"Correlates events to instances.
import io.cratis.chronicle.events.EventType
import io.cratis.chronicle.projections.FromEvent
import io.cratis.chronicle.readModels.ReadModel
@EventType
data class OrderShipped(val orderId: String, val carrier: String)
@ReadModel
@FromEvent(OrderPlaced::class)
@FromEvent(OrderShipped::class)
data class OrderTracking(
val orderId: String = "",
val status: String = ""
)

Applied to a read model property to override auto-mapping by name and declare which event field populates it. It is repeatable, so one property can be mapped differently per event type.

ParameterTypeDefaultDescription
propertyPathString""Path to the source property.
eventTypeKClass<*>Nothing::classEvent it applies to.

propertyPath is a dot-separated path on the event, and defaults to the annotated property’s own name. The default eventType applies the mapping to every event in the read model’s @FromEvent list that has a matching source property.


Populates a read model property by joining against another event type on its event source id. Use it when the triggering event doesn’t carry the read model’s own key but instead references another entity by id.

ParameterTypeDefaultDescription
eventTypeKClass<*>The event class to join against.
onString""Read model property to join on.
eventPropertyNameString""Property on eventType to read.

on and eventPropertyName both default to the annotated property’s own name.

import io.cratis.chronicle.projections.Join
import io.cratis.chronicle.readModels.ReadModel
@ReadModel
data class OrderWithCustomerEmail(
val orderId: String = "",
val customerId: String = "",
@Join(
eventType = CustomerRegistered::class,
on = "customerId",
eventPropertyName = "email"
)
val customerEmail: String = ""
)

Declares that a collection property is populated with child read model instances created or updated by a specific event type.

ParameterTypeDefaultDescription
eventTypeKClass<*>The event class that creates children.
keyString"EventSourceId"Event property identifying the child.
identifiedByString""Child’s own identity property.
parentKeyString"EventSourceId"Event property for the parent.

identifiedBy defaults to the child type’s id/key property, falling back to EventSourceId.


Marks a single nullable property as a nested sub-object built from its own type’s @FromEvent/@SetFrom annotations.

No parameters.


Declares which event clears (nulls out) a @Nested property. Placed on the nested type itself, alongside its @FromEvent annotation.

ParameterTypeDescription
eventTypeKClass<*>The event class that clears the nested object.

Turns a property into an occurrence counter for a specific event type — every time eventType fires for the read model instance, the property is bumped by one.

ParameterTypeDefaultDescription
eventTypeKClass<*>The event class to count occurrences of.
constantKeyString""See “Constant keys” below.

Bumps a numeric property up (@Increment) or down (@Decrement) by one every time eventType fires for the read model instance.

ParameterTypeDefaultDescription
eventTypeKClass<*>The event class that bumps the property.
constantKeyString""See “Constant keys” below.
import io.cratis.chronicle.projections.Increment
import io.cratis.chronicle.readModels.ReadModel
@ReadModel
data class OrderShipmentStats(
val orderId: String = "",
@Increment(OrderShipped::class) val shipmentCount: Int = 0
)

Constant keys: when constantKey is set on @Count, @Increment, or @Decrement, every occurrence of eventType updates the same read model instance, identified by that constant value, instead of the projection’s normal per-instance key resolution.


Adds (@AddFrom) or subtracts (@SubtractFrom) the value of an event property into/from a numeric property every time eventType fires.

ParameterTypeDefaultDescription
eventTypeKClass<*>The event class carrying the value.
eventPropertyNameString""Property on eventType to read.

eventPropertyName defaults to the annotated property’s own name.


Projects a property from every event type the projection observes, rather than a single one. @FromAll and @FromEvery are equivalent aliases.

ParameterTypeDefaultDescription
propertyString""Triggering event property to read from.
contextPropertyString""Event context property to read from.

Both default to the annotated property’s own name. contextProperty (e.g. the causing identity) takes precedence over property when both are set.


Marks a projection as forward-only — it cannot be rewound and replayed from scratch. Placed on the read model class.

No parameters.


Declares which event removes a read model instance, or — when placed on a @ChildrenFrom property — which event removes a single child from that collection.

ParameterTypeDefaultDescription
eventTypeKClass<*>The event class that triggers removal.
keyString"EventSourceId"Event property for what to remove.
parentKeyString"EventSourceId"Event property for the parent.

parentKey only applies when removing a single child from a @ChildrenFrom collection.


Like @RemovedWith, but the removal event doesn’t directly carry the id — it’s resolved via a join instead.

ParameterTypeDefaultDescription
eventTypeKClass<*>The event class that triggers the removal.
keyString"EventSourceId"Property used in the join lookup.

Disables AutoMap. Placed on a read model, @ChildrenFrom element, or @Nested type, it disables AutoMap entirely for that type. Placed on a single property, it excludes just that property from AutoMap while siblings keep auto-mapping.

No parameters.


Marks a class as a discoverable Chronicle webhook definition. The class must implement IWebhookDefiner.

ParameterTypeDefaultDescription
idString""Stable identifier. Defaults to class name.
targetUrlStringThe URL to send events to.
import io.cratis.chronicle.webhooks.IWebhookDefiner
import io.cratis.chronicle.webhooks.IWebhookDefinitionBuilder
import io.cratis.chronicle.webhooks.Webhook
@Webhook(targetUrl = "https://hooks.example.com/orders")
class OrderPlacedWebhook : IWebhookDefiner {
override fun define(builder: IWebhookDefinitionBuilder) {
builder.withEventType(OrderPlaced::class)
}
}