Form controller that auto-populates a form bean from the request.
This, either using a new bean instance per request, or using the same bean
when the sessionForm property has been set to true.
This class is the base class for both framework subclasses like SimpleFormController and AbstractWizardFormController , and custom form controllers you can provide yourself.
Both form-input views and after-submission views have to be provided programmatically. To provide those views using configuration properties, use the SimpleFormController .
Subclasses need to override showForm to prepare the form view,
and processFormSubmission to handle submit requests. For the latter,
binding errors like type mismatches will be reported via the given "errors" holder.
For additional custom form validation, a validator (property inherited from
BaseCommandController) can be used, reporting via the same "errors" instance.
Comparing this Controller to the Struts notion of the Action
shows us that with Spring, you can use any ordinary JavaBeans or database-
backed JavaBeans without having to implement a framework-specific class
(like Struts' ActionForm). More complex properties of JavaBeans
(Dates, Locales, but also your own application-specific or compound types)
can be represented and submitted to the controller, by using the notion of
a java.beans.PropertyEditor. For more information on that
subject, see the workflow of this controller and the explanation of the
BaseCommandController .
Workflow
(and that defined by superclass):
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
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.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.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 In session form mode, a submission without an existing form object in the session is considered invalid, like in case of a resubmit/reload by the browser. The handleInvalidSubmit method is invoked then, by default trying to resubmit. It can be overridden in subclasses to show corresponding messages or to redirect to a new form, in order to avoid duplicate submissions. The form object in the session can be considered a transaction token in that case.
Note that views should never retrieve form beans from the session but always from the request, as prepared by the form controller. Remember that some view technologies like Velocity cannot even access a HTTP session.
Exposed configuration properties
(and those defined by superclass):
| name | default | description |
| bindOnNewForm | false | Indicates whether to bind servlet request parameters when creating a new form. Otherwise, the parameters will only be bound on form submission attempts. |
| sessionForm | false | Indicates whether the form object should be kept in the session when a user asks for a new form. This allows you e.g. to retrieve an object from the database, let the user edit it, and then persist it again. Otherwise, a new command object will be created for each request (even when showing the form again after validation errors). |
kml
| Fields inherited from org.springframework.context.supportApplicationObjectSupport |
|---|
| Fields inherited from org.springframework.web.servlet.mvcBaseCommandController |
|---|
| Fields inherited from org.springframework.web.servlet.supportWebContentGenerator |
|---|
| Constructor Summary |
|---|
|
Create a new AbstractFormController. |
| Method Summary | |
|---|---|
| protected Object |
Return the current form object to use for binding and further processing, based on the passed-in form object as found in the HttpSession. |
| protected Object |
Retrieve a backing object for the current form from the given request. |
| protected Object |
Return the form object for the given request. |
| protected BindException |
Create a BindException instance for a new form. |
| protected String |
Return the name of the HttpSession attribute that holds the form object for this form controller. |
| protected String |
Return the name of the HttpSession attribute that holds the form object for this form controller. |
| protected ModelAndView |
Handle an invalid submit request, e.g. |
| protected ModelAndView |
Handles two cases: form submissions and showing a new form. |
| boolean |
Return if request parameters should be bound in case of a new form. |
| protected boolean |
Determine if the given request represents a form submission. |
| boolean |
Return if session form mode is activated. |
| protected void |
Callback for custom post-processing in terms of binding for a new form. |
| protected void |
Callback for custom post-processing in terms of binding for a new form. |
| protected ModelAndView |
Process form submission request. |
| protected Map |
Create a reference data map for the given request, consisting of bean name/bean instance pairs as expected by ModelAndView. |
| void |
Set if request parameters should be bound to the form object in case of a non-submitting request, i.e. |
| void |
Activate resp. |
| protected ModelAndView |
Prepare the form model and view, including reference and error data. |
| protected ModelAndView |
Prepare model and view for the given form, including reference and errors. |
| protected ModelAndView |
Prepare model and view for the given form, including reference and errors, adding a controller-specific control model. |
| protected ModelAndView |
Show a new form. |
| Methods inherited from org.springframework.web.servlet.mvcAbstractController |
|---|
| Methods inherited from org.springframework.contextApplicationContextAware |
|---|
| Methods inherited from org.springframework.context.supportApplicationObjectSupport |
|---|
| Methods inherited from org.springframework.web.servlet.mvcController |
|---|
| Methods inherited from java.langObject |
|---|
| Methods inherited from org.springframework.web.context.supportWebApplicationObjectSupport |
|---|
public AbstractFormController
(
)
The default implementation simply returns the session form object as-is. Subclasses can override this to post-process the session form object, for example reattaching it to a persistence manager.
The properties of the form object will correspond to the form field values in your form view. This object will be exposed in the model under the specified command name, to be accessed under that name in the view: for example, with a "spring:bind" tag. The default command name is "command".
Note that you need to activate session form mode to reuse the form-backing object across the entire form workflow. Else, a new instance of the command class will be created for each submission attempt, just using this backing object as template for the initial form.
Default implementation calls BaseCommandController.createCommand,
creating a new empty instance of the command class.
Subclasses can override this to provide a preinitialized backing object.
Calls formBackingObject if not in session form mode.
Else, retrieves the form object from the session. Note that the form object
gets removed from the session, but it will be re-added when showing the
form for resubmission.
showNewForm.
Can be used directly when intending to show a new form but with
special errors registered on it (for example, on invalid submit).
Usually, the resulting BindException will be passed to
showForm, after registering the errors on it.
Default implementation delegates to the getFormSessionAttributeName
version without arguments.
Default is an internal name, of no relevance to applications, as the form session attribute is not usually accessed directly. Can be overridden to use an application-specific attribute name, which allows other code to access the session attribute directly.
protected
ModelAndView
handleInvalidSubmit
(
HttpServletRequest
request,
HttpServletResponse
response
)
Default implementation simply tries to resubmit the form with a new form object. This should also work if the user hit the back button, changed some form data, and resubmitted the form.
Note: To avoid duplicate submissions, you need to override this method.
Either show some "invalid submit" message, or call showNewForm for
resetting the form (prepopulating it with the current values if "bindOnNewForm"
is true). In this case, the form object in the session serves as transaction token.
protected ModelAndView handleInvalidSubmit(HttpServletRequest request, HttpServletResponse response) throws Exception {
return showNewForm(request, response);
}
You can also show a new form but with special errors registered on it:
protected ModelAndView handleInvalidSubmit(HttpServletRequest request, HttpServletResponse response) throws Exception {
BindException errors = getErrorsForNewForm(request);
errors.reject("duplicateFormSubmission", "Duplicate form submission");
return showForm(request, response, errors);
}
protected
ModelAndView
handleRequestInternal
(
HttpServletRequest
request,
HttpServletResponse
response
)
isFormSubmission,
always treating requests without existing form session attribute
as new form when using session form mode.
public
boolean
isBindOnNewForm
(
)
Default implementation treats a POST request as form submission. Note: If the form session attribute doesn't exist when using session form mode, the request is always treated as new form by handleRequestInternal.
Subclasses can override this to use a custom strategy, e.g. a specific request parameter (assumably a hidden field or submit button name).
public
boolean
isSessionForm
(
)
protected
void
onBindOnNewForm
(
HttpServletRequest
request,
Object
command,
BindException
errors
)
bindOnNewForm is true.
Default implementation delegates to onBindOnNewForm(request, command).
onBindOnNewForm version
with all parameters, after standard binding when displaying the form view.
Only called if bindOnNewForm is set to true.
Default implementation is empty.
protected
ModelAndView
processFormSubmission
(
HttpServletRequest
request,
HttpServletResponse
response,
Object
command,
BindException
errors
)
handleRequestInternal
in case of a form submission, with or without binding errors. Implementations
need to proceed properly, typically showing a form view in case of binding
errors or performing a submit action else.
Subclasses can implement this to provide custom submission handling
like triggering a custom action. They can also provide custom validation
and call showForm or proceed with the submission accordingly.
For a success view, call errors.getModel() to populate the
ModelAndView model with the command and the Errors instance, under the
specified command name, as expected by the "spring:bind" tag. For a form view,
simply return the ModelAndView object provided by showForm.
Default implementation returns null. Subclasses can override this to set reference data used in the view.
public
void
setBindOnNewForm
(
boolean
bindOnNewForm
)
public
void
setSessionForm
(
boolean
sessionForm
)
This is necessary for either wizard-style controllers that populate a single form object from multiple pages, or forms that populate a persistent object that needs to be identical to allow for tracking changes.
protected
ModelAndView
showForm
(
HttpServletRequest
request,
HttpServletResponse
response,
BindException
errors
)
A typical implementation will call
showForm(request, errors, "myView")
to prepare the form view for a specific view name, returning the
ModelAndView provided there.
For building a custom ModelAndView, call errors.getModel()
to populate the ModelAndView model with the command and the Errors instance,
under the specified command name, as expected by the "spring:bind" tag.
You also need to include the model returned by referenceData.
Note: If you decide to have a "formView" property specifying the view name, consider using SimpleFormController.
protected
ModelAndView
showForm
(
HttpServletRequest
request,
BindException
errors,
String
viewName
)
In session form mode: Re-puts the form object in the session when returning to the form, as it has been removed by getCommand.
Can be used in subclasses to redirect back to a specific form page.
protected
ModelAndView
showForm
(
HttpServletRequest
request,
BindException
errors,
String
viewName,
Map
controlModel
)
In session form mode: Re-puts the form object in the session when returning to the form, as it has been removed by getCommand.
Can be used in subclasses to redirect back to a specific form page.
protected
ModelAndView
showNewForm
(
HttpServletRequest
request,
HttpServletResponse
response
)
Subclasses should set the following properties, either in the constructor or via a BeanFactory: commandName, commandClass, bindOnNewForm, sessionForm. Note that commandClass doesn't need to be set when overriding
formBackingObject, as the latter determines the class anyway."cacheSeconds" is by default set to 0 (-> no caching for all form controllers).