I am currently in the process of updating some of our portlets to use Spring 3.1 and the new Portlet 2.0 spec in preparation with a portal framework upgrade taking place for ZotPortal this summer. A problem we were experiencing using the new Spring 3.0 annotations for our portlets was the new way Spring handles validation/binding errors for forms. Before, the validation is done in the action phase, then the error(s) are stored in the model attribute, and if errors are present you can redirect back to the render phase so the initial page form will be displayed again with the submitted data but this time displayed with error messages that explain to the user why it failed validation. I was surprised when the validation would fail this time and redirect back to the page form but no errors would show. Apparently something changed in the way Spring handles objects placed into the model via the @ModelAttribute annotation. Now Spring would replace an object even if it is associated with errors and they will not be present/displayed when redirected back to the form.
A few solutions have been proposed across the spring forms, stackoverflow, and the interwebs;
- Validate the form object during the render phase as well. This will generate the errors and have them displayed on the form when the rendering completes
- Explicitly preserve the form object or errors after the redirect and ensure they get passed to the form when rendering completes
- Instead of using @ModelAttribute, persist the form object as a session attribute so it persists across the action and render phases
Option 1 isn’t an option for our applications. In the initial render phases the form object would not pass our validation tests because it isn’t filled out yet! We don’t want to display validation error messages to the user upon the first load of the form when they haven’t had a chance to submit any data yet, it would seem a bit rude in my opinion. Validation should occur if data has been submitted. Option 3 seemed to be overkill, submitting a simple form shouldn’t need to persist the form object in the session which lives well past the action phase of the submit. I believe Spring has some nice ways of handling these session attributes, but I haven’t played with it very much.
I decided to use option 2. When the render phase is deciding what object to populate the form with it first checks to see if an applicable object with errors already exists in the model, if it does it lets that object stay in the model to populate the form. The previous submitted data and errors get passed through the render phase and displayed on the form for the user to see and fix so it can be validated properly.
I wrote an example for persisting the object and it seems the same result can be accomplished by persisting the errors object instead, but I haven’t tested that. Options 1 and 3 can also be found in this thread.