What I'm trying to accomplish is to access my Spring Session within a custom constraint
Sample scenario:
Custom constraint @UniqueEmail verifies that the email is not already in use in the system. This validation is performed on the edit endpoint and should be ignore if the user didn't change the email, 1st: because there's no need for it and 2nd: because querying the db for that email will actually return a result, which is the user itself, although there's no way of telling it without accessing the session
This works:
If I use model attributes with custom editor though @InitBinder I can set a property in the to-be-validated bean before the validation occurs like so
@InitBinder(value="myModelObj")
protected void initBinder(WebDataBinder binder, HttpSession session) {
User user = (User) session.getAttribute("user");
binder.registerCustomEditor(User.class, "user", new UidPropertyEditor(user));
}
@RequestMapping(...)
public String updateUser(@Valid @ModelAttribute("myModelObj") MyModelObj form){
...
}
MyModelObj has an attribute which will be replaced with the actual session user. Problems:
This does not work
The new endpoints have to use @RequestBody rather than @ModelAttribute, which means that (afaik) @InitBinder won't work anymore, hence losing access to the session object.
How (if possible) can I access the session from within the custom constraint?
public class EmailIsUniqueStringValidator implements ConstraintValidator<EmailIsUnique, String> {
@Autowired
private UserDAO userDAO;
HttpSession session; //Somehow initialized
@Override
public void boolean isValid(String email, ConstraintValidatorContext context) {
User user = (User) session.getAttribute("user");
if(user.getEmail().equals(email)){
return true; // No need to validate
}
else if(userDAO.emailInUse(email)) {
return false;
}
}
Non-ideal approach:
What I'm doing now is performing the session-dependant validations in the controller manually, which means I have 2 points where validation is performed.
There are some other interesting options in this post too, but if there was a way to access the session...
Thanks in advance
This can be achieved using RequestContextHolder like so:
public class EmailIsUniqueStringValidator implements ConstraintValidator<EmailIsUnique, String> {
@Autowired
private UserDAO userDAO;
HttpSession session;
@Override
public void boolean isValid(String email, ConstraintValidatorContext context) {
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
session = attr.getRequest().getSession();
User user = (User) session.getAttribute("user");
if(user.getEmail().equals(email)){
return true; // No need to validate
}
else if(userDAO.emailInUse(email)) {
return false;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With