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