A API Bean Validations permite incluir anotações no código que dizem como os campos serão validados pela aplicação.
Abaixo temos um exemplo de algumas anotações básicas existentes na API:
public class User { @NotNull @Email private String email; public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } } @ValidateParams public class UserService { public void createUser(@Email String email, @NotNull String name) { ... } }
Junto com a estrutura desenvolvida no Identity, tais anotações são validadas automaticamente quando a classe ou o método possui a anotação @ValidateParams.
Para isso, as anotações de validação devem ser colocadas na classe de Implementação e também nas Interfaces onde os métodos são definidos.
A anotação @ValidateParams deve ser colocada somente na implementação.
public class ServiceInterface { public void createUser(@Email String email, @NotNull String name); }
@ValidateParams public class ServiceImpl { public void createUser(@Email String email, @NotNull String name){ //... } }
Agrupamento de Validações
É possível agrupar validações em uma mesma validação personalizada, conforme exemplo abaixo, que faz várias validações em um único parâmetro.:
@ValidateParams public class CarService { public void findCar(@NotNull @NotBlank @NotEmpty @Pattern(regex="[A-Z]{3}\d{4}") String plate) { ... } }
Para simplificar, poderíamos criar uma validação personalizada, combinando todas essas validações em uma única validação (@Plate)
@ValidateParams public class CarService { public void findCar(@Plate String plate) { ... } }
Para isso, é necessário criar uma anotação nova, seguindo alguns padrões.
// agrupamento das validações utilizadas @NotNull @NotEmpty @NotBlank @Pattern(regex="[A-Z]{3}\d{4}") // Elementos onde essa anotação pode ser colocada @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) // Anotação que indica que esta é uma anotação de validação @Constraint(validatedBy = {}) // Anotação que indica que todas as anotações agrupadas serão tratadas como uma unica violação @ReportAsSingleViolation public @interface Plate { // Identificação da mensagem a ser exibida String message() default "{com.totvs.custom.validation.plate.message}"; // Permite definir grupos com outras anotações Class<?>[] groups() default {}; // Área para inclusão de dados genéricos Class<? extends Payload>[] payload() default {}; }
É possível também criar validadores customizados para as anotações.
Seguindo o exemplo acima, poderíamos incluir uma verificação no Detran, para verificar se a placa é realmente válida, para isso, é necessário escrever código para realizar essa consulta.
Com algumas modificações, é possível incluir um validador customizado para essa tarefa:
@NotNull @NotEmpty @NotBlank @Pattern(regex="[A-Z]{3}\d{4}") @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) // Classe que irá fazer a validação no Detran @Constraint(validatedBy = DetranValidator.class) @ReportAsSingleViolation public @interface Plate{ String message() default "{com.totvs.custom.validation.plate.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
public class DetranValidator implements ConstraintValidator<Plate, String> { private CaseMode caseMode; @Override public void initialize(CheckCase constraintAnnotation) { this.caseMode = constraintAnnotation.value(); } @Override public boolean isValid(String object, ConstraintValidatorContext constraintContext) { var validDetran = pesquisaDetran(); // logica de pesquisa no detran if ( validDetran ) { return true; } return false; } }