Here's a general thumb rule that I follow:
When using bean validation, specify
rules that do not require dependencies
on other beans. The moment you depend
on another bean, get your service
layer to handle that dependency.
In other words, if you have a reference to a bean inside another, avoid putting in that @NotNull constraint. Your service layer is best used for that, for you're catching the violation much earlier, and at a more logical point (since other business validations would assume that the beans are available).
As an example, consider the following entity (apologies for it wont compile)
@Entity
public class User
{
@Id
private int id;
@NotNull
private String fullName;
@NotNull
private String email;
private Set<Role> roles; //No bean validation constraints here.
...
public boolean mapRoleToUser(Role role)
{ //Validation is done here. Including checks for a null role.
}
}
@Entity
public class Role
{
@Id
private int id;
@NotNull
private String name;
}
The service layer in this case, is the one that should validate whether the user has a role attached or not. Verification in the pre-persist or pre-update phase is a bit too late, especially when there is a distinct service layer that has business logic, and the rest of the business logic in the domain model (sadly, I haven't seen a good enough application with all of the logic in the domain model alone).