0

I have a FacesValidator class named UniqueEmailValidator to determine that the entered email is unique or not.

I need the userService variable, so i inject it by spring.

Here is the UniqueEmailValidator.java :

@FacesValidator("com.obs.bean.uniqueEmailValidator")
@Component
public class UniqueEmailValidator implements Validator {

    @Autowired
    private UserService userService;

    public void validate(FacesContext fc, UIComponent uic, Object value) throws ValidatorException {
        if (value == null) {
            return;
        }
        String email = (String) value;
        System.out.println("userService before use: " + userService); // null
        boolean exists = userService.emailExists(email);
        if (exists) {
            throw new ValidatorException(new FacesMessage(
                    FacesMessage.SEVERITY_ERROR, "Email already in use", null));
        }
    }
}

Here is the UserServiceImple.java:

@Service
public class UserServiceImpl implements UserService<User, Integer>, Serializable {

@Autowired
@Qualifier("userDao")
private UserDao userDao;

@Transactional()
public boolean emailExists(String value) {
    Query query = userDao.getSession().createQuery("from User where email=?");
    query.setString(0, value);
    if (query.uniqueResult() != null) {
        return true;
    }
    return false;
  }
}

But the userService is null, (I get nullPointerException)

I have also This lines in applicationContext.xml:

<!-- Activates scanning of @Autowired -->
<context:annotation-config/>

<!-- Activates scanning of @Repository and @Service -->
<context:component-scan base-package="..."/>
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • Looks like JSF is managing the instance of `UniqueEmailValidator` and not Spring, thus you cannot inject any object. – Luiggi Mendoza May 08 '15 at 22:07
  • @LuiggiMendoza So is there any solution? –  May 09 '15 at 08:08
  • I won't use a validator for this case, as simple as that. – Luiggi Mendoza May 09 '15 at 08:09
  • @LuiggiMendoza So how you recognize the entered email is unique or not? –  May 09 '15 at 08:11
  • 1
    For this specific case, I would set a unique key in database, try to insert and handle the exception for unique key constraint not met. If you still want/need to display a nice message to user for validation, then I would recommend processing this validation in the `action`. It's not the right approach but is what you can do for this case. Also, I would submit a ticket to JSF guys to add support for injection of CDI/Spring/Guice beans on validators and converters. – Luiggi Mendoza May 09 '15 at 08:14
  • 1
    By the way, mkyong has this covered: http://www.mkyong.com/jsf2/spring-autowired-into-jsf-custom-validator/ – Luiggi Mendoza May 09 '15 at 08:16
  • @LuiggiMendoza Your link solved my problem, Thanks. –  May 09 '15 at 08:20

2 Answers2

2

When you enable the validator with the tag

<f:validator validatorId="validatorId"/>

then the validator instance is created by the JSF implementation (by getting the Class and just calling newInstance()), hence it is not recognized as Spring bean and autowiring doesn't work. To get the validator instance as Spring bean, you have to use the binding attribute:

<f:validator binding="#{validatorBeanName}"/>

In that case, the annotation @FacesValidator isn't necessary.

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
dunni
  • 43,386
  • 10
  • 104
  • 99
0

You can try to use parametrized declaration for your autowired service

@Autowired
private UserService<User, Integer> userService;

Or try to use @Qualifier and give a name to your service

@Service("myService")
public class UserServiceImpl ...

...

@Autowired
@Qualifier("myService")
private UserService<User, Integer> userService;
Dédé Lolo
  • 144
  • 4