Home > Net >  Custom bean validation is not being called at all
Custom bean validation is not being called at all

Time:08-27

I'm trying to create a custom bean validator, but, no matter what I do, the validator methods are not being called at all. All the other validation annotations are working perfectly.

This is the annotation:

package com.ats.boleta.validation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MaxDateValidator.class)
@Documented
public @interface MaxDate {

    String message() default "Data está acima do máximo permitido.";
    String string();
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};    

}

This is the validator:

package com.ats.boleta.validation;

import java.time.LocalDate;
import java.time.temporal.Temporal;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
 * @author Haroldo de Oliveira Pinheiro
 * @see https://gist.github.com/MottoX/e689adf41c22a531af4e18ce285690eb
 */
public class MaxDateValidator implements ConstraintValidator<MaxDate, Temporal> {
    
    private LocalDate maxValue;
    
    @Override
    public void initialize(MaxDate constraintAnnotation) {
        this.maxValue = LocalDate.parse(constraintAnnotation.string());
    }

    @Override
    public boolean isValid(Temporal value, ConstraintValidatorContext context) {
        return value == null || !LocalDate.from(value).isAfter(this.maxValue);
    }
}

This is the main DTO that is being validated:

package com.ats.boleta.model.dto;

import java.util.List;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

import com.ats.boleta.model.Boleto;
import com.ats.boleta.model.Cedente;
import com.ats.boleta.model.Titulo;
import com.ats.boleta.validation.PrefixConstraint;

import lombok.Data;
import lombok.ToString;

@Data
@ToString
public class BoletoDTO {

    @NotBlank(message = "Nome não pode ficar em branco.")
    private String nome;
    
    @PrefixConstraint(message = "Cedente")
    @NotNull(message = "Cedente não pode ficar em branco.")
    private Cedente cedente;
    
    @Valid
    @NotEmpty(message = "Não foi informado nenhum título.")
    private List<Titulo> titulo;
        
}

And this is the child DTO where @MaxDate is being used:

(...)
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class Titulo {

    @NotBlank(message = "Número do documento não pode ficar em branco.")
    private String numeroDocumento = "";
    
    private Integer nossoNumero;
    
    @NotNull(message = "Carteira não pode ficar em branco.")
    private Integer carteira;
    
    private String valorDocumento = "";
    
    @MaxDate(string = "2099-12-31", message = "Data de vencimento não pode ser posterior a 2099")
    private LocalDate dataVencimento; 
    (...)
    
}

And this is the controller:

package com.ats.boleta.controller;

(...)

@Slf4j
@RestController
@RequestMapping("/v0/boleto")
public class BoletaController {
    (...)

    @RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_PDF_VALUE)
    public ResponseEntity<InputStreamResource> boleto(@Valid @RequestBody BoletoDTO dto) throws IOException {
        (...)
    }

    @RequestMapping(value = "/remessa", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE)
    public ResponseEntity<InputStreamResource> remessa(@RequestBody BoletoDTO dto) throws IOException {
        (...)
    }

}

No matter what I do, neither MaxDateValidator.initialize(MaxDate) nor MaxDateValidator.isValid(Temporal, ConstraintValidatorContext) are called, no matter what. No exception is thrown, no warnings appear in the log, none of the aforementioned methods are called. All of the other annotations work as intended.

I have even tried to change the generic on MaxDateValidator to either LocalDate or even Object; nothing works.

What could be causing this behavior? Is there any way to debug it? Are there any Spring logs that could be activated to check what would be going wrong?

CodePudding user response:

In the end, I had forgotten to add the @Valid annotation to the remessa() method on the controller:

package com.ats.boleta.controller;

(...)

@Slf4j
@RestController
@RequestMapping("/v0/boleto")
public class BoletaController {
    (...)

    @RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_PDF_VALUE)
    public ResponseEntity<InputStreamResource> boleto(@Valid @RequestBody BoletoDTO dto) throws IOException {
        (...)
    }

    @RequestMapping(value = "/remessa", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE)
    public ResponseEntity<InputStreamResource> remessa(@Valid @RequestBody BoletoDTO dto) throws IOException {
        (...)
    }

}

CodePudding user response:

Can you please try to use:

@NotEmpty(message = "Não foi informado nenhum título.")
private List<@Valid Titulo> titulo;

Instead of:

@Valid
@NotEmpty(message = "Não foi informado nenhum título.")
private List<Titulo> titulo;

Please add annotation @Valid for method remessa

package com.ats.boleta.controller;

(...)

@Slf4j
@RestController
@RequestMapping("/v0/boleto")
public class BoletaController {
(...)

@RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<InputStreamResource> boleto(@Valid @RequestBody BoletoDTO dto) throws IOException {
    (...)
}

@RequestMapping(value = "/remessa", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE)
public ResponseEntity<InputStreamResource> remessa(@Valid @RequestBody BoletoDTO dto) throws IOException {
    (...)
}

}
  • Related