Árvore de páginas

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:

Validações Básicas
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.:

    Multiplas Validações
    @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)

    Validações Agrupadas
    @ValidateParams
    public class CarService {
    
      public void findCar(@Plate String plate) {
        ...
      }
    }

    Para isso, é necessário criar uma anotação nova, seguindo alguns padrões.

    Validação Customizada
    // 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:

      @Plate
      @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 {};
      }
      
      



      DetranValidator
      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;
      	}
      }