2

I have taken the reference to fix the problem of repository injection into Custom ConstraintValidator from from this post however after spending few hours I am still not able to autowire repository into my custom constraint validator.

Am I missing something over here? I am using the latest version of spring-boot:2.3.1

UserValidator.java

@Component
public class UserValidator implements ConstraintValidator<ValidateUser, User> {

    private boolean isValid = true;
    @Autowired
    private UserRepository userRepository;
    BiConsumer<User, ConstraintValidatorContext> registerUserValidator = (user, context) -> {
        if (StringUtils.isBlank(user.getUserName())) addError("Username is mandatory", context);
        if (StringUtils.isBlank(user.getEmail())) addError("Email ID is mandatory", context);
        if (StringUtils.isBlank(user.getPassword())) addError("Password is mandatory", context);

        if (StringUtils.isBlank(user.getUserType()))
            addError("User Type [Distributor/Investor] is mandatory", context);

        if (Optional.of(userRepository.findByEmailAndUserType(user.getEmail(), user.getUserType())).isEmpty())
            addError("Email already registered", context);

        if (user.getUserType().equals(UserType.Distributor) && Optional.of(userRepository.findByArn(user.getArn())).isPresent())
            addError("ARN [" + user.getArn() + "] already registered.", context);

        if (user.getUserType().equals(UserType.Investor) && Optional.of(userRepository.findByPan(user.getPan())).isPresent())
            addError("PAN [" + user.getPan() + "] already registered.", context);
    };

    @Override
    public boolean isValid(User user, ConstraintValidatorContext context) {
        if (user.getAction() == Action.REGISTER_USER) registerUserValidator.accept(user, context);
        return isValid;
    }

    private void addError(String errorMessage, ConstraintValidatorContext context) {
        context.disableDefaultConstraintViolation();
        context.buildConstraintViolationWithTemplate(errorMessage).addConstraintViolation();
        isValid = false;
    }

    }

ValidateUser.java

import org.springframework.stereotype.Component;

import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.ReportAsSingleViolation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;

@Documented
@Constraint(validatedBy = UserValidator.class)
@Target({METHOD, CONSTRUCTOR, FIELD, PARAMETER, TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@ReportAsSingleViolation
public @interface ValidateUser {

    String message() default "Invalid User";

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

    Class<? extends Payload>[] payload() default {};

}

UserController.java

@RestController
@RequestMapping(path = "/v1/user")
public class UserController {

    @Autowired
    private ModelValidator validator;
    @Autowired
    private UserManager userManager;

    @PostMapping(value = "")
    public ResponseEntity<User> register(@RequestBody User user) {
        validator.validate(user, Action.REGISTER_USER);
        ...
        ...

pom.xml

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
    </parent>

    <properties>
        <java.version>11</java.version>
        <boot.version>1.4.0.RELEASE</boot.version>
        <swagger.version>2.9.2</swagger.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

ValidationConfig.java

import org.hibernate.validator.HibernateValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory;

import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

@Configuration
public class ValidationConfig {

    @Bean
    public Validator validator(@Autowired AutowireCapableBeanFactory autowireCapableBeanFactory) {
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class).configure()
                .constraintValidatorFactory(new SpringConstraintValidatorFactory(autowireCapableBeanFactory))
                .buildValidatorFactory();
        Validator validator = validatorFactory.getValidator();

        return validator;
    }
}

User.java

import com.fasterxml.jackson.annotation.JsonIgnore;
import org.maruti.mfm.validator.ValidateUser;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@ValidateUser
@Document
public class User extends BaseEntity {
Jigar Naik
  • 1,946
  • 5
  • 29
  • 60
  • Always use constructor injection instead of field injection when it's possible. This will probably identify the origin of your problem for you. – chrylis -cautiouslyoptimistic- Aug 05 '20 at 03:41
  • @chrylis-cautiouslyoptimistic-yes, I have tried that but that does not resolve the issue. here the instance is not managed by spring, so it fails. I believe after adding ValidationConfig the instance creation should have been managed by spring – Jigar Naik Aug 06 '20 at 01:50
  • Hello. Have you found a solution to this problem? – lemario May 26 '21 at 12:35

0 Answers0