I\'m a bit of a Java EE/EJB noob, but from the docs and other posts I\'ve gathered you cannot query the database using the same entitymanager/session during entity validatio
I think I get your desire to do all the validation using the awesome bean validation API, but remember that is not required.
Furthermore, think about these two requirements:
The first clearly only depends on the password itself and I would classify it as validating data and therefore such validation belongs in the data layer.
The second depends on the relation of a piece of data with a number of other entities, or with the current state of the system. I would classify this as something that belongs in the business layer.
That said, instead of trying to put the validation constraints on the entity class, put them on some business layer class (yes, you can even use bean validation if you so desire now).
For example, say you have a User entity with current password field and a Passwords entity from which you can query for a user's old passwords. Now make your user data access object:
@Stateful // yes stateful, need the same instance across method invocations
@ValidatePassword
public class UserDao {
@PersistenceContext private EntityManager em;
private String password;
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isValidPassword() {
// use the em to find the old passwords
// check that the submitted password is valid
}
public void savePassword() {
// find the user
// set the user's now valid password
}
}
Create your class-level constraint:
@Target( { TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = MyPasswordValidator.class)
public @interface ValidatePassword {
String message() default "error message";
Class>[] groups() default {};
Class extends Payload>[] payload() default {};
}
And validator:
public class MyPasswordValidator implements ConstraintValidator {
public void initialize(SelfValidating constraintAnnotation) {
// get message, etc.
}
public boolean isValid(UserDao userDao, ConstraintValidatorContext constraintValidatorContext) {
return userDao.isValidPassword();
}
}
Something like this should do it. As a side effect, since the actual validation is done by an EJB now, the validation logic itself will be transacted, if you leave the default transnational attributes that is.