Search code examples
spring-bootspring-mvcspring-data-jpaspring-datahibernate-validator

A field's value should be either empty or valid ISBN


Form

@Getter
@Setter
public class SourceForm {

    @ISBN(type = ISBN.Type.ANY)    
    private String isbn;
}

Entity

@Entity
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "sources")
public class SourceEntity  extends BaseEntity{
    @ISBN(type = ISBN.Type.ANY)
    @Column(columnDefinition = "varchar(255) default ''",
            nullable = false)
    private String isbn;   

}

Problem

Isbn field can be empty. In other words: either empty or valid ISBN.

But if I leave this field empty in the form, I get the error message "invalid ISBN".

What can I try next?


Solution

  • The default behavior of the @ISBN annotation is not to consider empty values as valid ISBNs. However, you can implement a custom validator to allow an empty value or validate ISBNs. Here's an example of how you can create a custom validator for this scenario:

    @Constraint(validatedBy = { EmptyOrValidISBNValidator.class })
    @Target({ ElementType.FIELD })
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface EmptyOrValidISBN {
    
        String message() default "Invalid ISBN";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }
    

    And the implementation of the custom validator:

    public class EmptyOrValidISBNValidator implements ConstraintValidator {
    
    @Override
    public void initialize(EmptyOrValidISBN constraintAnnotation) {
        // Initialization logic, if any
    }
    
    @Override
    public boolean isValid(String isbn, ConstraintValidatorContext context) {
        // Implement your own validation logic here
        // You can use the provided isbn parameter to validate if the ISBN is not empty or null, and if it is valid
        // Return true if the isbn is empty or valid, otherwise return false
        // For example, you can use regular expressions or external libraries to perform the ISBN validation
    
        // Validate if the ISBN is not empty or null and if it already exists
        if (Strings.isNotEmpty(isbn)) {
            return isValidIsbn10(isbn) || isValidIsbn13(isbn);
        }
        return true;
    }
    
    private boolean isValidIsbn10(String isbn) {
        String regex = "^(?:\\d{9}[\\d|Xx])|(?:\\d{1,5}-\\d{1,7}-\\d{1,6}-[\\d|Xx])$";
        return Pattern.matches(regex, isbn);
    }
    
    private boolean isValidIsbn13(String isbn) {
        String regex = "^(?:\\d{12}\\d|[\\d|-]{1,5}-\\d{1,7}-\\d{1,6}-\\d)$";
        return Pattern.matches(regex, isbn);
    }
    

    }

    You can then use the @EmptyOrValidISBN annotation on your field in your code, and the custom validator EmptyISBNValidator will allow empty values or valid ISBNs according to the defined logic.