Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Vader & the Army of Validators

Vader & the Army of Validators

A generic bean validation framework built & consumed by teams at Salesforce, to cater specific validation needs of Salesforce REST APIs. It abstracts away the validation complexity and promotes low-code config-based validation. This is built entirely using FOSS libraries and is about ripe to open-source.

Gopal S Akshintala

October 05, 2021
Tweet

More Decks by Gopal S Akshintala

Other Decks in Programming

Transcript

  1. @GopalAkshintala Why a new Framework? Salesforce core has no de-facto

    standard for Bean validation Same Validations, Different execution strategy per context (like FailFast or ErrorAccumulate) No easy way to share validations among Beans that share common DS
  2. @GopalAkshintala Why a new Framework? Salesforce core has no de-facto

    standard for Bean validation Same Validations, Different execution strategies No easy way to share validations among Beans that share common DS
  3. @GopalAkshintala 🧶 Enable them to Configure POJO/Bean Validations ⚙ Supply

    them the Algorithm for their Execution 
 Strategy & DS (Like Fail-Fast for Batch) VadeR’s Business (Dev Teams as Customers)
  4. @GopalAkshintala Customers in Production 4 Teams Rev Hydra Rev Delphinus

    Rev Centaurus Rev Pegasus In 3 different domains Payments Tax Billing
  5. @GopalAkshintala Presented @ Confs 🇺🇸 All Things Open, 2020, Raleigh,

    USA. 📹 🏴󠁧󠁢󠁥󠁮󠁧󠁿 Kotlin User Group, London 🇩🇪 Berlin Functional Programming Group 🇳🇴 JavaBin, Norway 🇩🇪 Kotlin User Group, Berlin 🇮🇳 Google Developer Group Devfest 2019 🇮🇳 Java User Group Hyderabad (@JUGHyd) 🇮🇳 Salesforce, Hyderabad, India 🇮🇳 Kotlin User Group, Hyderabad 🇪🇸 JBCN Conf, 2020, Barcelona, Spain
  6. Validator: (ValidatableT) -> FailureT Validator<Bean, ValidationFailure> validator = bean ->

    { if (bean == null) { return new ValidationFailure(FIELD_NULL_OR_EMPTY); } else { return ValidationFailure.NONE; } }; @GopalAkshintala
  7. Validator: (ValidatableT) -> FailureT static ValidationFailure validator(Bean bean) { if

    (bean == null) { return new ValidationFailure(FIELD_NULL_OR_EMPTY); } else { return ValidationFailure.NONE; } } @GopalAkshintala
  8. @GopalAkshintala Consumer defines the FailureT Some examples of what a

    FailureT may include: Localised error message API error codes Exception handling
  9. @GopalAkshintala Hook Validators with Config var config = ValidationConfig.<Bean, ValidationFailure>toValidate()

    .withValidators(Tuple.of(validatorChain, ValidationFailure.NONE)) .prepare(); Validator<Bean, ValidationFailure> validator1 = bean -> ValidationFailure.NONE; Validator<Bean, ValidationFailure> validator2 = bean -> ValidationFailure.NONE; Validator<Bean, ValidationFailure> validator3 = bean -> ValidationFailure.UNKNOWN_EXCEPTION; List<Validator<Bean, ValidationFailure >> validatorChain = List.of(validator1, validator2, validator3); Optional<ValidationFailure> result = Vader.validateAndFailFast(Validatable, config);
  10. @GopalAkshintala Configure Mandatory fields Strict SF ID field validations Multi-Filter

    conditions to handle duplicates in a batch Min/Max batch size check with combination of multiple batch members Validators Plug-&-Play
  11. @GopalAkshintala Configure Mandatory Fields ValidationConfig.<Bean, ValidationFailure>toValidate() .shouldHaveFieldsOrFailWithFn(Tuple.of( List.of( Bean ::

    getRequiredField1, Bean :: getRequiredField2, Bean :: getRequiredList), (missingFieldName, missingFieldValue) -> getFailureWithParams(REQUIRED_FIELD_MISSING, missingFldName, missingFldValue))) .prepare();
  12. @GopalAkshintala Configure Mandatory fields Strict SF ID field validations Multi-Filter

    conditions to handle duplicates in a batch Min/Max batch size check with combination of multiple batch members Validators Plug-&-Play
  13. @GopalAkshintala Configure SF ID Fields ValidationConfig.<BeanWithIdFields, ValidationFailure>toValidate() .withIdConfig( IDConfig.<BeanWithIdFields, ValidationFailure,

    EntityId>toValidate() .withIdValidator(ValidIdUtil :: isThisEntity) .shouldHaveValidSFIdFormatForAllOrFailWithFn(Tuple.of( Map.of( BeanWithIdFields : : getAccountId, AccountUddConstants.EntityId, BeanWithIdFields : : getContactId, ContactUddConstants.EntityId), (invalidIdFldName, invalidIdFldValue) -> getFailureWithParams(INVALID_UDD_ID, invalidIdFldName, invalidIdFldValue)))) .prepare();
  14. @GopalAkshintala Configure Mandatory fields Strict SF ID field validations Multi-Filter

    conditions to handle duplicates in a batch Min/Max batch size check with combination of multiple batch members Plug-&-Play Validators
  15. @GopalAkshintala Configure Multi-Filter for Batch BatchValidationConfig.<MultiKeyBean, ValidationFailure>toValidate() .findAndFilterDuplicatesConfigs(List.of( FilterDuplicatesConfig.<MultiKeyBean, ValidationFailure>toValidate()

    .findAndFilterDuplicatesWith(id1Mapper) .andFailDuplicatesWith(DUPLICATE_ITEM_1), FilterDuplicatesConfig.<MultiKeyBean, ValidationFailure>toValidate() .findAndFilterDuplicatesWith(id2Mapper) .andFailDuplicatesWith(DUPLICATE_ITEM_2))) .prepare();
  16. @GopalAkshintala Configure Mandatory fields Strict SF ID field validations Multi-Filter

    conditions to handle duplicates in a batch Min/Max batch size check with combination of multiple batch members Specs Validators Plug-&-Play
  17. @GopalAkshintala Configure Batch-Size ContainerValidationConfig.<ContainerWithMultiBatch, ValidationFailure>toValidate() .withBatchMappers(List.of( ContainerWithMultiBatch :: getBatch1, ContainerWithMultiBatch

    :: getBatch2)) .shouldHaveMinBatchSizeOrFailWith(Tuple.of(1, MIN_BATCH_SIZE_NOT_MET)) .shouldHaveMaxBatchSizeOrFailWith(Tuple.of(10, MAX_BATCH_SIZE_EXCEEDED)) .prepare(); Criteria: 1 <= size(batch1 + batch2) <= 10
  18. @GopalAkshintala Configure Mandatory fields Strict SF ID field validations Multi-Filter

    conditions to handle duplicates in a batch Min/Max batch size check with combination of multiple batch members Specs Validators Plug-&-Play
  19. @GopalAkshintala Specs 🤓 Low-code Validations spec._2() .when(Bean :: getStartDate) .then(Bean

    :: getEndDate) .shouldRelateWithFn(isOnOrBeforeIfBothArePresent()) .orFailWith(ofFieldIntegrity(INVALID_START_AND_END_DATES))
  20. @GopalAkshintala 🎛 Config based Validation Perks🍫 Low Learning-curve Readability Maintainability

    Less Complexity Testability Flexibility Extensibility Re-usability/Sharing
  21. @GopalAkshintala Vader Current Applications Connect REST API Validations SObject Validation

    hooks FTests But it’s Generic! Independent of Consumer’s Implementation