Custom constraint showing error on field

Tested with jmix version 2.4.1 and 2.4.5
Jmix studio 2.5.0-242

I want a validation message to appear on the zipcode field, but the error is showing as a notification on the form

image

@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ZipCodeCountryValidator.class)
public @interface ValidZipCodeCountry {
    String message() default "Invalid zip code for the specified country";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}
public class ZipCodeCountryValidator implements ConstraintValidator<ValidZipCodeCountry, Example> {

    @Override
    public void initialize(ValidZipCodeCountry constraintAnnotation) {
        // Initialization code, if needed
    }

    @Override
    public boolean isValid(Example example, ConstraintValidatorContext context) {
        if (example == null) {
            return true;
        }

        String countryCode = example.getCountryCode();
        String zipCode = example.getZipCode();

        if (countryCode == null) {
            return true;
        }

        // Validation logic for Belgium (countryCode "be")
        if ("be".equalsIgnoreCase(countryCode)) {
            if (zipCode == null || zipCode.length() != 4) {
                context.disableDefaultConstraintViolation();
                context.buildConstraintViolationWithTemplate("Zip code must be 4 digits long for country code 'be'")
                        .addPropertyNode("zipCode")
                        .addConstraintViolation();
                return false;
            }
        }

        return true;
    }
}
@JmixEntity
@Table(name = "EXAMPLE")
@Entity
@ValidZipCodeCountry
public class Example {
    @JmixGeneratedValue
    @Column(name = "ID", nullable = false)
    @Id
    private UUID id;

    @Column(name = "COUNTRY_CODE")
    private String countryCode;

    @Column(name = "ZIP_CODE")
    private String zipCode;

    public String getZipCode() {
        return zipCode;
    }

    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }

    public String getCountryCode() {
        return countryCode;
    }

    public void setCountryCode(String countryCode) {
        this.countryCode = countryCode;
    }

    public UUID getId() {
        return id;
    }

    public void setId(UUID id) {
        this.id = id;
    }
}

I created a sample project to demonstrate the problem
SampleValidation.zip (111.8 KB)

What am I doing wrong?

Hi!

You defined a bean validation that works at the data model level: Bean Validation :: Jmix Documentation

Because it works at the data model level, this validation doesn’t have access to visual component. That is why the notification is shown as a popup window.

In your case, if you need validation related to a visual component, you need to define a custom validator for the component and specify it in XML.

Documentation link: Validator :: Jmix Documentation

If you need custom validation logic for multiple fields so that you can manage the state UI components, you can use the onValidation handler in the controller:
https://docs.jmix.io/jmix/flow-ui/views/view-events.html#validation-event

Best regards,
Dmitriy