Constraints
Constraints are shared Chronicle behavior. The shared docs cover constraint concepts, model-bound constraints, declarative constraints, and client-tabbed examples.
Kotlin client: constraint scoping
Section titled “Kotlin client: constraint scoping”IConstraintBuilder (passed into IConstraint.define) can scope every
constraint added through it to a narrower uniqueness dimension than the
whole event store:
| Member | Scopes uniqueness checking per… |
|---|---|
perEventSourceType | Event source type |
perEventStreamType | Event stream type |
perEventStreamId | Event stream id |
Combine any of the three; by default (none called) a constraint is checked globally across the whole event store:
import io.cratis.chronicle.constraints.Constraintimport io.cratis.chronicle.constraints.IConstraintimport io.cratis.chronicle.constraints.IConstraintBuilderimport io.cratis.chronicle.events.EventType
@EventTypedata class ConstraintsBridgeUserRegistered( val userId: String = "", val email: String = "")
@Constraintclass ConstraintsBridgeUniqueEmail : IConstraint { override fun define(builder: IConstraintBuilder) { builder .perEventSourceType() .unique { unique -> unique .on( ConstraintsBridgeUserRegistered::class, ConstraintsBridgeUserRegistered::email ) .withMessage("Email must be unique per event source type.") } }}Kotlin client: unique over several properties
Section titled “Kotlin client: unique over several properties”Pass more than one property to on when the value that must be unique is
the combination of them. Here a person is rejected only when both the first
and the last name match an existing one; sharing just one of them is fine.
ignoreCasing() applies to every property in the constraint:
import io.cratis.chronicle.constraints.Constraintimport io.cratis.chronicle.constraints.IConstraintimport io.cratis.chronicle.constraints.IConstraintBuilderimport io.cratis.chronicle.events.EventType
@EventTypedata class ConstraintsBridgePersonRegistered( val firstName: String = "", val lastName: String = "")
@Constraintclass ConstraintsBridgeUniqueFullName : IConstraint { override fun define(builder: IConstraintBuilder) { builder.unique { unique -> unique .on( ConstraintsBridgePersonRegistered::class, ConstraintsBridgePersonRegistered::firstName, ConstraintsBridgePersonRegistered::lastName ) .ignoreCasing() } }}Call on once per event type, each with its own properties, to make one
constraint span several event types. Calling on a second time for the same
event type throws EventTypeAlreadyAddedToUniqueConstraint - list every
property in one call - and a unique { } block that never calls on throws
NoEventTypesAddedToUniqueConstraint.
When a constraint spans several event types that each have several properties, every type must list the same number of properties in the same order, because the kernel combines the values in declaration order.
Java client: unique over several properties
Section titled “Java client: unique over several properties”Java names the properties as strings through UniqueConstraintBuilderJavaBridge;
pass as many as make up the unique value:
import io.cratis.chronicle.constraints.Constraint;import io.cratis.chronicle.constraints.IConstraint;import io.cratis.chronicle.constraints.IConstraintBuilder;import io.cratis.chronicle.events.EventType;import io.cratis.chronicle.java.UniqueConstraintBuilderJavaBridge;
@EventTyperecord ConstraintsBridgePersonRegistered(String firstName, String lastName) {}
@Constraintclass ConstraintsBridgeUniqueFullName implements IConstraint { @Override public void define(IConstraintBuilder builder) { builder.unique(unique -> { UniqueConstraintBuilderJavaBridge .on(unique, ConstraintsBridgePersonRegistered.class, "firstName", "lastName") .ignoreCasing(); }); }}