Yes SimpleFormController has been deprecated since Spring 3.0 but is still widely used. So in this post I am going to discuss the lifecycle or workflow of this controller.
Workflow is as follows and it is controlled by
- The controller receives a request for a new form (typically a GET).
- Call to formBackingObject() which by default, returns an instance of the commandClass that has been configured (see the properties the superclass exposes), but can also be overridden to e.g. retrieve an object from the database (that needs to be modified using the form).
- Call to initBinder() which allows you to register custom editors for certain fields (often properties of non-primitive or non-String types) of the command class. This will render appropriate Strings for those property values, e.g. locale-specific date strings.
- Only if bindOnNewForm is set to true, then ServletRequestDataBinder gets applied to populate the new form object with initial request parameters and the onBindOnNewForm(HttpServletRequest, Object, BindException) callback method is called. Note: any defined Validators are not applied at this point, to allow partial binding. However be aware that any Binder customizations applied via initBinder() (such as DataBinder.setRequiredFields(String) will still apply. As such, if using bindOnNewForm=true and initBinder() customizations are used to validate fields instead of using Validators, in the case that only some fields will be populated for the new form, there will potentially be some bind errors for missing fields in the errors object. Any view (JSP, etc.) that displays binder errors needs to be intelligent and for this case take into account whether it is displaying the initial form view or subsequent post results, skipping error display for the former.
- Call to showForm() to return a View that should be rendered (typically the view that renders the form). This method has to be implemented in subclasses.
- The showForm() implementation will call referenceData(), which you can implement to provide any relevant reference data you might need when editing a form (e.g. a List of Locale objects you're going to let the user select one from).
- Model gets exposed and view gets rendered, to let the user fill in the form.
- The controller receives a form submission (typically a POST). To use a different way of detecting a form submission, override the isFormSubmission method.
- If sessionForm is not set, formBackingObject() is called to retrieve a form object. Otherwise, the controller tries to find the command object which is already bound in the session. If it cannot find the object, it does a call to handleInvalidSubmit which - by default - tries to create a new form object and resubmit the form.
- The ServletRequestDataBinder gets applied to populate the form object with current request parameters.
- Call to onBind(HttpServletRequest, Object, Errors) which allows you to do custom processing after binding but before validation (e.g. to manually bind request parameters to bean properties, to be seen by the Validator).
- If validateOnBinding is set, a registered Validator will be invoked. The Validator will check the form object properties, and register corresponding errors via the given Errors object.
- Call to onBindAndValidate() which allows you to do custom processing after binding and validation (e.g. to manually bind request parameters, and to validate them outside a Validator).
- Call processFormSubmission() to process the submission, with or without binding errors. This method has to be implemented in subclasses.
Above was the workflow as specified in the Spring documentation of AbstractFormController.
If it's confusing refer to following diagrammatic representations and try to co-relate
Note : If there are any errors in command object fields binding form will be reloaded (as shown in Request 2 of above diagram and after processFormSubmission(), showForm() and referenceData() are again called). onSubmit() is never called if this happens.
Typically a Spring bean lifecycle of a SimpleFormController would look something like below -
Understanding some basic methods
- isFormSubmission() : This method determines whether form is submitted (a POST request) or is for initial viewing (a GET request). This method is the base on which the two workflows of SimpleFormController are split.
- formBackingObject() : This method returns an instance of command object which is the form Object. You can specify the class of this Object by setCommandClass( ) method. Or you can directly specify it in your bean configuration file -
- initBinder() : This method is called after the form command object is created and data binder is created by the controller. Developers can override this method to register custom PropertyEditor.
- isValidateOnBinding(): If this method returns true then the binding validations are performed. By default it is set to true and final. Only way to change it is through setValidateOnBinding() method.
- referenceData(): This method is used to provide reference data if any. Do not confuse it with formBackingObject() method where form Object is created. This method is used to provide any extra reference data that model may need to render UI page other that the command object. Whole model is then sent to the View set by formView property of the bean in file. Form View will then be rendered (See above diagrams for reference).