0

I made a custom validation annotation for unique email (When user registers itself, program checks if email is already in database).

Everything works just fine, but when I need to modify user's info and not to create a new one I run into a problem that says "Email is already in use"

Can I somehow turn off only @EmailAvailablity validation(I need the others like email pattern and password validation)?

All validation annotations are in the same User bean.

These ARE MY CUSTOM VALIDATOR CLASS

  1. User AVailablity
package com.vicky.finalYearProject.customValidations;

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;

@Constraint(validatedBy = UserAvailabilityValidator.class)
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserAvailability {
    
    public String message() default "Email is already Registered";
    
    public Class<?>[] groups() default { };
    
    public Class<? extends Payload>[] payload() default { };
    
}
  1. Constraint Validator
package com.vicky.finalYearProject.customValidations;

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

import com.vicky.finalYearProject.Service.CheckUserAvailabilityService;

public class UserAvailabilityValidator implements ConstraintValidator<UserAvailability, String>{

    CheckUserAvailabilityService availabilityService = new CheckUserAvailabilityService();
    
    @Override
    public void initialize(UserAvailability constraintAnnotation) {
        ConstraintValidator.super.initialize(constraintAnnotation);
        
    }
    
    @Override
    public boolean isValid(String email, ConstraintValidatorContext context) {
        return availabilityService.isAvailable(email);//return true or false;
    }

}

i have checked one question similar :

How to prevent Spring validation on update

but i cant understand it...

Thank You.

1 Answers1

0

As this is a custom validator, you should consider adding the condition yourself, e.g. based on an ID which is only generated on save. For that purpose, making it a class-level constraint would be helpful, allowing you to check multiple values of your class.

Something like:

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@Constraint(validatedBy = [EmailAvailabilityValidator::class])
annotation class EmailAvailability(
    val message: String = "Email must be available",
    val groups: Array<KClass<*>> = [],
    val payload: Array<KClass<out Any>> = []
)

class EmailAvailabilityValidator : ConstraintValidator<EmailAvailability, User> {

    override fun isValid(value: User?, context: ConstraintValidatorContext?): Boolean {
        if (value == null) return true
        if (value.id != null) return true // don't execute it on saved entities
        // your extra validation
    }
}

Alternatively, when using Hibernate, here's a proposal on making validations only run on insert: Hibernate validations on save (insert) only

Besides that I would consider moving this check out of the bean. It sounds like you do any kind of database interaction in the validation. Coupling the model to the database breaks encapsulation and limits your test capabilities. Adding e.q. uniqueness to a column would be an alternative.

Dirk Bolte
  • 572
  • 4
  • 12