Skip to main content

Validation

The API generated with the rest-expanders comes with (optional) validation features. This includes several validation mechanisms, grouped into two categories:

  • Input validation is validation that currently happens solely in the CONTROL layer. This validation only happens for endpoints that take input payloads (POST, PUT and PATCH).
  • Database validation is validation that requires database access, such as checkin whether something already exists in the system. These validations are implemented and executed in the LOGIC layer, but can also be called through a pipeline from the CONTROL layer. This is typically for URL validation, to verify that a requested resource exists.
Option
enableValidation Component

This option will enable the generation of validation infrastructure in the REST JAX-RS API. Almost all projects will want to use this option in combination with enableJaxrs.

<options>
<enableValidation/>
</options>

Default validations

Required fields

Option
isRequired Field

The option isRequired is an option introduced by the main expanders. If this option is added to a Field, this field should never be empty.

When the option exposeRestField is present, this option will add additional code to the input validation of the JAX-RS REST endpoints.

<options>
<isRequired/>
</options>

The REST expanders can generate validation for required fields when they are exposed with exposeRestField and have the option isRequired.

Expanded implementation in the InputValidator class for the POST endpoint
private void validateInput(MyElementPostInputModel inputModel) {
InputValidation validation = InputValidation.init(inputModel, "jsonInput")
.isRequired();

errors.addAll(validation.getErrors());

if (validation.hasNoErrors()) {
validateName(inputModel);
// @anchor:validateInput:start
// @anchor:validateInput:end
// anchor:custom-validateInput:start
// anchor:custom-validateInput:end
}
}

private void validateName(MyElementPostInputModel inputModel) {
InputValidation validation = InputValidation.init(inputModel.getName(), "name")
.isRequired()
.isString()
// @anchor:validate-office:start
// @anchor:validate-office:end
// anchor:custom-validate-office:start
// anchor:custom-validate-office:end
;

errors.addAll(validation.getErrors());
}

Aside from the input validation itself, a unit test will also be generated to verify that the input validation works correctly. Though with being generated, this does not necessarily add a lot of value to the project, but it does increase code coverage significantly.

Expanded implementation in the InputValidatorTest class for the POST endpoint
@Test
public void successNameIsRequired() {
model.setName("name");

final ValidationResult result = validator.validate(model);
assertThat(result.getErrors("name"),
not(hasItem(validationError(MISSING_REQUIRED_VALUE))));
}

Uniqueness

Option
isUnique Field

This option can be added to a field to indicate that it should be unique. The option is introduced by the REST expanders and only supported in the JAX-RS stack.

When the option exposeRestField is present, this option will add additional code to the database validation of the JAX-RS REST endpoints.

<options>
<isUnique/>
</options>

The REST expanders provide a method to check for uniqueness of individual fields (predating unique constraints) by adding the option isUnique to the field.

Implied uniqueness

info

It is not recommended to rely on implied uniqueness. Ideally explicitly define the option isUnique in the model to indicate that the field is assumed to be always unique.

The option generateUuid is part of the functionality of Expanders. When added to a field, this option ensures that a new UUID will be generated for that field in the Cruds.create() method whenever a new instance of the DataElement is created. The REST expanders assume that the option isUnique is implicit when this option is added to a field, as it ensures that a unique UUID is always generated. In that case, all properties of the isUnique option will also apply to the field.

caution

The value if_empty changes the behavior of the option generateUuid. When this value is added, a UUID is only generated when no value is given for that field when calling the Cruds.create() method. This implies that a UUID (or another value) can be supplied rather than generates and as such the property of this value always being unique can no longer be guaranteed, as generateUuid by itself does not validate uniqueness. When this is the case, the REST expanders no longer assume that isUnique is implied and it must be added explicitly if the field is used as the functionalKey, which must always be unique for the REST API to function correctly. The REST expanders will generate a data validation to verify that the value supplied for the field in the POST endpoint is effectively unique. The field can be exposed through the POST endpoint, but only through PUT and PATCH if it is not the functionalKey, as then it is used to uniquely identify the resource and should not be altered afterwards.