I have a Spring MVC controller and when an exception occurs I would like to show the exception message in the view and rollback the open transactions. The view contains a form like this:
<form:form method="POST" modelAttribute="registrationForm">
<form:errors path="*" cssClass="error-message"/>
...
</form:form>
I would like to show the exception message in the view, using the <form:errors ... /> feature. This is my current quite horrible solution:
@RequestMapping(value = "/registration", method = RequestMethod.POST)
public ModelAndView submitForm(@ModelAttribute("registrationForm") RegistrationForm registrationForm,
BindingResult result,
ModelAndView modelAndView,
HttpServletRequest request) throws Exception
{
registrationValidator.validate(registrationForm, result);
if(result.hasErrors())
{
return setupForm(modelAndView, registrationForm);
}
else
{
try
{
// ... Some non-transactional operations...
// The following operation is the only one annotated with @Transactional
// myExampleDao is @Autowired, can throw exception
myExampleDao.createFoo(bar);
// ... Other non-transactional operations...
return new ModelAndView("redirect:successful");
}
catch(Exception e)
{
throw new RegistrationException(e, registrationForm, result);
}
}
}
@ExceptionHandler(value = RegistrationException.class)
public ModelAndView registrationExceptionHandler(RegistrationException e) throws Exception
{
RegistrationForm registrationForm = e.getRegistrationForm();
BindingResult result = e.getBindingResult();
result.reject("exception", e.getMessage());
Map<String, Object> model = result.getModel();
return setupForm(new ModelAndView("registration", model), registrationForm);
}
private ModelAndView setupForm(ModelAndView modelAndView, RegistrationForm registrationForm) throws Exception
{
Map<String,Object> model = modelAndView.getModel();
model.put("currentYear", Calendar.getInstance().get(Calendar.YEAR));
return new ModelAndView("registration", model);
}
The problem I’m facing is that when the exception is thrown, the transaction is not rolled back.
Can anyone help?
Thank you.
Update: slightly changed the question for better understanding
Update: found a quite horrible solution to display the exception message in the view. Still facing the problem with the transaction that is not rolled back when the exception is thrown.
Update: I changed @Transactional to @Transactional(rollbackFor = Exception.class) in the MyExampleDao.createFoo(...) method and now everything is working perfectly. This solution is still ugly IMO, does anyone have a better solution?
No one suggested a better solution than my ugly one. Here is my solution that solved the problem I had: