-
Notifications
You must be signed in to change notification settings - Fork 2
Adding Simple Validators
Gal Koren edited this page Nov 12, 2020
·
1 revision
Let’s validate the ads headline is no longer than 256 chars.
class HeadlineLengthValidator implements FieldValidator<AdEntity, String> {
@Override
public EntityField<AdEntity, String> validatedField() {
return AdEntity.HEADLINE;
}
@Override
public ValidationError validate(String value) {
return value != null && value.length() > 256
? new ValidationError("headline cannot exceed 256 chars")
: null;
}
}
Performance notes:
- The fields validator is only triggered if the command contains the validated field (
HEADLINE
) and if the old value (currently in DB) is different than the new value (in the command). - The old value is fetched from DB only if the command contains the validated field.
- To minimize DB access, fetching from DB is done in a single query at the beginning of the flow and not one command at a time.
Let's go back to our AdPersistence
class where we left an empty lonely flow.
private ChangeFlowConfig.Builder<AdEntity> flowBuilder() {
return changeFlowConfigBuilder.newInstance(AdEntity.INSTANCE)
.withValidator(buildChangesValidator(AdEntity.INSTANCE, asList(
//
// list of validators comes here
//
new HeadlineLengthValidator()
)));
}
Now let's have a validation rule based on multiple fields, HEADLINE
and URL
class WhenUrlContainsKenshooThenHeadlineMustContainKenshoo implements FieldsCombinationValidator<AdEntity> {
@Override
public Stream<EntityField<AdEntity, ?>> validatedFields() {
return Stream.of(AdEntity.HEADLINE, AdEntity.URL);
}
@Override
public ValidationError validate(FieldsValueMap<AdEntity> values) {
return values.get(URL).contains("kenshoo") && !values.get(HEADLINE).contains("kenshoo")
? new ValidationError("URL contains kenshoo but HEADLINE doesn't");
: null;
}
}
Examples become more complicated as we go :)
Now we also want fields from ancestor entities. Suppose our Ad entity belongs to a Campaign entity and it has a CAMPAIGN_ID field referencing the campaign (more about relations in later chapters). Suppose Campaign has a CAMPAIGN_TYPE field. Let's create some complex validation rule:
class UrlMustStartWithHttpsForVideoCampaigns implements FieldComplexValidator<AdEntity, String> {
@Override
public EntityField<EntityForTest, String> validatedField() {
return AdEntity.URL;
}
@Override
public Stream<EntityField<?, ?>> fetchFields() {
return Stream.of(CampaignEntity.CAMPAIGN_TYPE);
}
@Override
public ValidationError validate(String url, CurrentEntityState otherValues) {
return otherValues.get(CAMPAIGN_TYPE) == CampaignType.VIDEO && !url.startsWith("https")
? new ValidationError("an Ad URL must start with https on a video campaigns");
: null;
}
}
Setting up an Entity Persistence
Query language
Building the Flow
- Adding Simple Validators
- State Consumers
- Adding a Custom Validator
- Enrichers
- Output Generators
- Customizing Flows
- Primary and Secondary Tables (detailed example)
- State Consumers and Relations (what can we fetch)
- Child Commands
- Cascade Delete