Inject Service in ConstraintValidator [Bean Validator - JSR 303] Spring
Asked Answered
R

4

28

Good Afternoon,

I am having problem to inject a service within a Bean Validator (JSR 303). I would be performing a validation, but I need to validate this record in my database;

When I use my service it throws NullPointerException;

Exception:

Exception in thread "main" javax.validation.ValidationException: HV000028: Unexpected exception during isValid call.
at org.hibernate.validator.internal.engine.ConstraintTree.validateSingleConstraint(ConstraintTree.java:294)
at org.hibernate.validator.internal.engine.ConstraintTree.validateConstraints(ConstraintTree.java:164)
at org.hibernate.validator.internal.engine.ConstraintTree.validateConstraints(ConstraintTree.java:125)
at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:86)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:442)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:387)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:351)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:303)
at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:133)
at net.pontoall.hemisphere.core.validation.impl.TesteValidator.main(TesteValidator.java:25)



Caused by: java.lang.NullPointerException
at net.pontoall.hemisphere.core.validation.impl.UsuarioValidatorImpl.doCheckLogin(UsuarioValidatorImpl.java:48)
at net.pontoall.hemisphere.core.validation.impl.UsuarioValidatorImpl.isValid(UsuarioValidatorImpl.java:26)
at net.pontoall.hemisphere.core.validation.impl.UsuarioValidatorImpl.isValid(UsuarioValidatorImpl.java:1)
at org.hibernate.validator.internal.engine.ConstraintTree.validateSingleConstraint(ConstraintTree.java:291)
... 9 more

Annotation:

@Target(value = ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UsuarioValidatorImpl.class)
public @interface UsuarioValidator {

String message() default "{net.pontoall.hemisphere.validation.UsuarioValidator.message}";

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

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

}

ValidatorImpl:

public class UsuarioValidatorImpl implements ConstraintValidator<UsuarioValidator, Usuario> {

@Autowired
private IUsuarioService service;

@Override
public void initialize(UsuarioValidator arg0) {

}

@Override
public boolean isValid(Usuario entidade, ConstraintValidatorContext ctx) {
    try {
        return (this.doCheckLogin(entidade, ctx) && this.doCheckEmail(entidade, ctx));
    } catch (HemisphereException e) {
        e.printStackTrace();
        return false;
    }
}

private boolean doCheckLogin(Usuario entidade, ConstraintValidatorContext ctx) throws HemisphereException {
    ctx.buildConstraintViolationWithTemplate("{net.pontoall.hemisphere.validation.UsuarioValidator.login.message}").addConstraintViolation();

    if (entidade.getId() == null) {
        // Novo Usuário
        Usuario original = service.buscarPorLogin(entidade.getLogin());

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

        return false;

    } else {

        Usuario original = service.obter(entidade.getId());
        if (original == null) {
            return true;
        } else {
            if (original.getLogin().equals(entidade.getLogin()) && original.getId().equals(entidade.getId())) {
                return true;
            }
        }

        return false;
    }
}

private boolean doCheckEmail(Usuario entidade, ConstraintValidatorContext ctx) {
    ctx.buildConstraintViolationWithTemplate("{net.pontoall.hemisphere.validation.UsuarioValidator.email.message}").addConstraintViolation();

    if (entidade.getId() == null) {
        // Novo Usuário
        Usuario original = service.buscarPorEmail(entidade.getEmail());

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

        return false;

    } else {

        Usuario original = service.obter(entidade.getId());
        if (original == null) {
            return true;
        } else {
            if (original.getEmail().equals(entidade.getEmail()) && original.getId().equals(entidade.getId())) {
                return true;
            }
        }

        return false;
    }
}
}
Racer answered 12/11, 2012 at 19:52 Comment(1)
Are you using Spring MVC, if so can you please show the configuration of Spring MVC alsoGuesswarp
M
17

You should set up a LocalValidatorFactoryBean in your Spring application context so you can retrieve Validator (and ValidatorFactory) instances via dependency injection.

By default, a validator obtained like that makes use of SpringConstraintValidatorFactory which provides dependency injection services to constraint validator implementations, as pointed out by Pangea.

Madcap answered 13/11, 2012 at 13:41 Comment(0)
P
1

Either build a ConstraintValidatorFactory or use SpringConstraintValidatorFactory if you want to wire dependencies.

Pollie answered 12/11, 2012 at 20:24 Comment(0)
M
1

You would have to write a custom ConstraintValidatorFactory. Just for your information though, Bean Validation 1.1 will allow for injection into the ConstraintValidatorFactory.

Mystagogue answered 13/11, 2012 at 10:23 Comment(0)
T
0

I "got it working" (spring-boot:2.5.7) by "just" :

@Component // mandatory!!! (or one of its descendants) to enable `@Autowired` 
@Scope("request") // not mandatory, but probably "good" for "validation"
public class UsuarioValidatorImpl implements ConstraintValidator<..., ...> ...

Alternatively you can define a @Bean public UsuarioValidator ... method in a @Configuration class....

But the key to auto-wire (any) two objects: Both have to be spring-managed!!

Tobey answered 22/11, 2021 at 16:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.