0

I know that this problem has been addressed/answered a zillion times in Stackoverflow and after I read about 85 percent of the question including the duplicates I still do not find a match to my case:

I have the following repository interface:

@Component
public interface IUserRepository {

    Boolean checkIfDuplicateName(String String);
}

that interface has a Repository implementation:

@Repository("userRepositoryImpl")
public class UserRepositoryImpl extends RepositoryImpl implements
        ApplicationEventPublisherAware, ApplicationContextAware,
        SessionFactoryAwareNode, IUserRepository {

    @Autowired
    private SessionFactory sessionFactory;

    ApplicationContext context;
    ApplicationEventPublisher eventPublisher;

    static Logger log = Logger.getLogger(UserRepositoryImpl.class.getName());

    public UserRepositoryImpl() {

    }

    public String eventTestPublish() {
        return "test of the event publisher finished succesefully";
}

    @Override
    public void setApplicationEventPublisher(
            ApplicationEventPublisher applicationEventPublisher) {
        this.eventPublisher = applicationEventPublisher;

    }

    @Override
    public void setApplicationContext(ApplicationContext context)
            throws BeansException {
        this.context = context;

    }

    public SessionFactory getSessionFactory() {
        return super.getSessionFactory();
    }

    @Override
    public void setSessionFactory(SessionFactoryImplementor sessionFactory) {
        this.sessionFactory = sessionFactory;

    }


    @Override
    public Boolean checkIfDuplicateName(String userName) {

    ....
    }

}

There is a service class:

@Service("userServiceImpl")
@Transactional
public class UserServiceImpl extends ServiceImpl  implements ApplicationEventPublisherAware, 
                                 ApplicationContextAware,
                                 SessionFactoryAwareNode,
                                 IUserService  {

    @Autowired
    public IUserRepository iuserRepository;

static Logger log = Logger.getLogger(UserServiceImpl.class.getName());

ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
Validator validator = vf.getValidator();
ExecutableValidator executableValidator = validator.forExecutables();

ApplicationContext context;
SessionFactory sessionFactory;
ApplicationEventPublisher eventPublisher;

public UserServiceImpl (){

}

@Override
public void setSessionFactory(SessionFactoryImplementor sessionFactory) {
    this.sessionFactory = sessionFactory;

}

@Override
public void setApplicationContext(ApplicationContext context)
        throws BeansException {
    this.context = context;

}

@Override
public void setApplicationEventPublisher(ApplicationEventPublisher arg0) {

}

...
...

}

If I @Autowire my repository Interface i.e. "public IUserRepository iuserRepository;" in my service class everything works fine, i.e. i DO NOT get any null NullPointerException. i.e. what i suppose is happening is spring creates the Proxy i.e. JDK dynamic proxies NOT CGLIB proxy as my Repository class implements an interface!!!

All works good and as expected however the same process does not work from another Validator class i.e. I have defined a Constrain/Annotation "@DuplicateUser":

@Target( {METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Constraint(validatedBy = DuplicateUserValidator.class)
@Documented
public @interface DuplicateUser {

    String message() default "{org.syncServer.ValidationAnnotations.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload> [] payload() default{};
}

this Constrain is implemented in a DuplicateUserValidator.class.:

@Component
public class DuplicateUserValidator implements ConstraintValidator<DuplicateUser, String> {

    @Autowired(required = true)
    public IUserRepository iuserRepository;

    public DuplicateUserValidator(){
        System.out.println("initializing DuplicateUserValidator");
        }

    public void initialize(DuplicateUser userName) {
    // do nothing
    }

    public boolean isValid(String str, ConstraintValidatorContext ctx) {
    return validate(str);
    }

    public boolean validate(final String userName) {
        Boolean result = false;
        result = iuserRepository.checkIfDuplicateName(userName);
        return result;

    }

In my DuplicateUserValidator.class i am trying to @Autowire the same repository interface (Not the Implementation Class) however whenever this Constrain is called the interface is always null. It is the same Interface that is being successfully @Autowired in the service tier.

I am using Spring Boot and i have placed the annotation

@ComponentScan(basePackages = "org.syncServer.*") 

under my Application.class, Also I have 5 another @Configuration classes (HibernatePersistence, Tomcat, MVC, Security, Security, WebSockets) they DO NOT have this Annotation on tom of them. All my Repository, DAO/Model, Service, Controller, CustomeAnnotations, Validators (including the DuplicateUserValidator class) classes are located under the "org.syncServer.*" structure.

My question is why the @Autowier of the "iuserRepository" Interface is NOT working in my DuplicateUserValidator class, but it is working from my Service Tier. When my Application starts I have a code that list all beans that are managed by Spring and "duplicateUserValidator" bean, as also the "userRepositoryImpl" bean are managed by spring. I also DO NOT use the "new" operator anywhere!!!!

One requirement that i have from the beginning is to code to interfaces thus CGLIB must NOT be used.

Any help is greatly appreciated.

related article Spring 3.1 Autowiring does not work inside custom constraint validator

releated article Autowiring a service into a validator

alexbt
  • 16,415
  • 6
  • 78
  • 87
Tito
  • 2,234
  • 6
  • 31
  • 65
  • related article http://stackoverflow.com/questions/12676299/spring-3-1-autowiring-does-not-work-inside-custom-constraint-validator – Tito Apr 24 '14 at 09:59
  • related article http://stackoverflow.com/questions/3587317/autowiring-a-service-into-a-validator/3587419#3587419 – Tito Apr 24 '14 at 14:22
  • How is the validator instance created? *You* may not be using `new`, but I bet your validator framework is calling `newInstance` on the class in the annotation. Put a breakpoint on the constructor and look at the stack trace. – chrylis -cautiouslyoptimistic- Apr 24 '14 at 16:30
  • possible duplicate of [Why is my Spring @Autowired field null?](http://stackoverflow.com/questions/19896870/why-is-my-spring-autowired-field-null) – chrylis -cautiouslyoptimistic- Apr 24 '14 at 16:34
  • 1
    remove `@Component` from `interface IUserRepository` is not need. – Abhishek Nayak Apr 24 '14 at 16:35
  • I found my problem. it turns out that hibernate was validating the object passed in my repository/dao tier. I did not expect hibernate was supposed to do that. Details of the problem can be found here http://davidmarquis.wordpress.com/tag/spring/ . Basically what i did is "javax.persistence.validation.mode=none" in my hibernate.properties. and then the validation was only done once in my service tier. – Tito Apr 29 '14 at 20:20

0 Answers0