Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring 3.1 Autowiring does not work inside custom constraint validator

I have an issue with bean autowiring inside a custom constraint validator. A constraint validator instance is not given using Spring's LocalValidatorFactoryBean. The JSR-303 provider is hibernate-validator 4.2.0.Final.

Spring configuration excerpt :

<!-- JSR 303 validation -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/> 

Custom Constraint Validator:

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

import org.springframework.beans.factory.annotation.Autowired;

import com.model.Subject;
import com.services.SomeTypeService;

public class ReadOnlyValidator implements ConstraintValidator<ReadOnly, String> {

@Autowired
private SomeTypeService someTypeService;

@Override
public void initialize(ReadOnly constraintAnnotation) { }

@Override
public boolean isValid(String type, ConstraintValidatorContext context) {
    try {
         if (null != type) {
                        return !someTypeService.isReadonly(type);
                     }
    } catch (Exception e) {
        e.printStackTrace();
    }

    return false;
}
}

Annotation:

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

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Target( { METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER } )
@Retention(RUNTIME)
@Constraint(validatedBy = ReadOnlyValidator.class)
@Documented
public @interface ReadOnly {
String message() default "{constraints.subjecttype.readonly}";
public abstract Class<?>[] groups() default {};
public abstract Class<? extends Payload>[] payload() default {};
}

SomeService:

 @Validated
 public interface SomeService {
    ...
    public void updateType(@ReadOnly String type) throws SomeException;
    ...
 }

SomeServiceImpl :

 @Service
 public class SomeServiceImpl implements SomeService {
  ...
    public void updateType(String type) throws SomeException {
     // do something
    }
  ...
 }

SomeTypeService is another @Service annotated bean that does not depend on SomeService ...

The problem is that I get an NPE as autowiring does not work; someone else is managing the custom validator instances and not Spring ...

Thanks in advance for any type of advice.

like image 834
Claudiu Muresan Avatar asked Oct 01 '12 15:10

Claudiu Muresan


1 Answers

Tito, please check if you can use something like below for Java config:

@Configuration
public class SampleConfig {
  ...

  @Bean
  public Validator validator() {
    return new LocalValidatorFactoryBean().getValidator();
  }

  @Bean
  public MethodValidationPostProcessor mvpp() {
    MethodValidationPostProcessor mvpp = new MethodValidationPostProcessor();
    mvpp.setValidator(validator());

    return mvpp;
  }

  ...
}

To reuse the validator bean in a different configuration bean, you can use the @Import annotation.

like image 193
Claudiu Muresan Avatar answered Oct 27 '22 17:10

Claudiu Muresan