Search code examples
javaspring-boothibernate-validator

Validation does not execute in service layer


hibernate-validator does not work in service layer on my spring boot project.

My domain model:

@Data
public class IssueAttachmentDto extends AttachmentDto {

    @NotEmpty
    private String issueId;

}

@Data
public class AttachmentDto {

    /**
     * Only allow digit 1~5
     */
    @NotEmpty
    @Pattern(regexp = "\\b[1-5]\\b")
    private String attachmentType;

    @NotEmpty
    @Valid
    private FileDto fileDto;
}

@Data
public class FileDto extends BaseDto {

    @NotEmpty
    private String fileType;

    /**
     * Only allow positive integer
     */
    @NotEmpty
    @Pattern(regexp = "^[0-9]*[1-9][0-9]*$")
    private Long fileSize;

    @NotEmpty
    private String fileKey;

    @NotEmpty
    private String fileName;
}

My service class:


@Slf4j
@Service
@Validated
public class AttachmentServiceImpl implements AttachmentService { 
  @Override
  public void uploadAttachment(IssueAttachmentDto issueAttachmentDto) {
    try {
      checkUploadAttachmentArgument(issueAttachmentDto);
    } catch (Exception e) {
      e.printStackTrace();
      throw e;
    }
        // something else...
  }

  private void checkUploadAttachmentArgument(@Valid IssueAttachmentDto issueAttachmentDto) {
    // something else
  }
}

My config class:

@Configuration
public class ConversionConfig {

    @Bean
    public ConversionService conversionService() {
        return new DefaultConversionService();
    }
}

The method checkUploadAttachmentArgument(@Valid IssueAttachmentDto issueAttachmentDto) never throws an exception whatever I pass. In my suppose, it will throws a ConstraintViolationException when I pass the illegal data. What's wrong with my code or my configuration, please help me.


Solution

  • Spring cannot proxy private methods - that is why you don't see any exception being thrown when invalid object is passed as an argument.

    Simply move the @Valid annotation to uploadAttachment method argument and it should work as expected. It should look like this:

    public void uploadAttachment(@Valid IssueAttachmentDto issueAttachmentDto) {
        // actual upload attachent logic
    }
    

    Edit:

    Even if Spring could proxy private methods it would not validate annotated argument in your case as you actually call checkUploadAttachmentArgument on an instance of the original class and not a proxy that additionally perform validation.