Class FormAction
- All Implemented Interfaces:
org.springframework.beans.factory.InitializingBean
,Action
Several action execution methods are provided:
-
setupForm(RequestContext)
- Prepares the form object for display on a form,creating it
and an associatederrors
if necessary, then caching them in the configuredform object scope
andform errors scope
, respectively. Alsoinstalls
any custom property editors for formatting form object field values. This action method will return the "success" event unless an exception is thrown. -
bindAndValidate(RequestContext)
- Binds all incoming request parameters to the form object and then validates the form object using aregistered validator
. This action method will return the "success" event if there are no binding or validation errors, otherwise it will return the "error" event. -
bind(RequestContext)
- Binds all incoming request parameters to the form object. No additional validation is performed. This action method will return the "success" event if there are no binding errors, otherwise it will return the "error" event. -
validate(RequestContext)
- Validates the form object using a registered validator. No data binding is performed. This action method will return the "success" event if there are no validation errors, otherwise it will return the "error" event. -
resetForm(RequestContext)
- Resets the form by reloading the backing form object and reinstalling any custom property editors. Returns "success" on completion, an exception is thrown when a failure occurs.
Since this is a multi-action a subclass could add any number of additional action execution methods, e.g. "setupReferenceData(RequestContext)", or "processSubmit(RequestContext)".
Using this action, it becomes very easy to implement form preparation and submission logic in your flow. One way to do this follows:
- Create a view state to display the form. In a render action of that state, invoke
setupForm
to prepare the new form for display. - On a matching "submit" transition execute an action that invokes
bindAndValidate
to bind incoming request parameters to the form object and validate the form object. - If there are binding or validation errors, the transition will not be allowed and the view state will automatically be re-entered.
- If binding and validation are successful go to an action state called "processSubmit" (or any other appropriate name). This will invoke an action method called "processSubmit" you must provide on a subclass to process form submission, e.g. interacting with the business logic.
- If business processing is ok, continue to a view state to display the success view.
Here is an example implementation of such a form flow:
<view-state id="displayCriteria"> <on-render> <evaluate expression="formAction.setupForm"/> </on-render> <transition on="search" to="executeSearch"> <evaluate expression="formAction.bindAndValidate"/> </transition> </view-state>
When you need additional flexibility consider splitting the view state above acting as a single logical form state into multiple states. For example, you could have one action state handle form setup, a view state trigger form display, another action state handle data binding and validation, and another process form submission. This would be a bit more verbose but would also give you more control over how you respond to specific results of fine-grained actions that occur within the flow.
Subclassing hooks:
- A important hook is
createFormObject
. You may override this to customize where the backing form object instance comes from (e.g instantiated transiently in memory or loaded from a database). - An optional hook method provided by this class is
initBinder
. This is called after a new data binder is created. - Another optional hook method is
registerPropertyEditors(PropertyEditorRegistry)
. By overriding it you can register any required property editors for your form. Instead of overriding this method, consider setting an explicitPropertyEditorRegistrar
strategy as a more reusable way to encapsulate custom PropertyEditor installation logic. - Override
validationEnabled(RequestContext)
to dynamically decide whether or not to do validation based on data available in the request context.
Note that this action does not provide a referenceData() hook method similar to that of Spring MVC's
SimpleFormController
. If you wish to expose reference data to populate form drop downs you can define a
custom action method in your FormAction subclass that does just that. Simply invoke it as either a chained action as
part of the setupForm state, or as a fine grained state definition itself.
For example, you might create this method in your subclass:
public Event setupReferenceData(RequestContext context) throws Exception { MutableAttributeMap requestScope = context.getRequestScope(); requestScope.put("refData", lookupService.getSupportingFormData()); return success(); }... and then invoke it like this:
<view-state id="displayCriteria"> <on-render> <evaluate expression="formAction.setupForm"/> <evaluate expression="formAction.setupReferenceData"/> </on-render> ... </view-state>This style of calling multiple action methods in a chain (Chain of Responsibility) is preferred to overriding a single action method. In general, action method overriding is discouraged.
When it comes to validating submitted input data using a registered Validator
,
this class offers the following options:
- If you don't want validation at all, just call
bind(RequestContext)
instead ofbindAndValidate(RequestContext)
or don't register a validator. - If you want piecemeal validation, e.g. in a multi-page wizard, call
bindAndValidate(RequestContext)
orvalidate(RequestContext)
and specify avalidatorMethod
action execution attribute. This will invoke the identified custom validator method on the validator. The validator method signature should follow the following pattern:public void ${validateMethodName}(${formObjectClass}, Errors)
For instance, having a action definition like this:<evaluate expression="formAction.bindAndValidate"> <attribute name="validatorMethod" value="validateSearchCriteria"/> </evaluate>
Would result in thepublic void validateSearchCriteria(SearchCriteria, Errors)
method of the registered validator being called if the form object class would beSearchCriteria
. - If you want to do full validation using the
validate
method of the registered validator, callbindAndValidate(RequestContext)
orvalidate(RequestContext)
without specifying a "validatorMethod" action execution attribute.
name | default | description |
formObjectName | formObject | The name of the form object. The form object will be set in the configured scope using this name. |
formObjectClass | null | The form object class for this action. An instance of this class will get populated and validated. Required when using a validator. |
formObjectScope | flow |
The scope in which the form object will be put. If put in flow scope the object will be cached and reused over the life of the flow, preserving previous values. Request scope will cause a new fresh form object instance to be created on each request into the flow execution. |
formErrorsScope | flash |
The scope in which the form object errors instance will be put. If put in flash scope form errors will be cached until the next user event is signaled. |
propertyEditorRegistrar | null | The strategy used to register custom property editors with the data binder. This is an alternative to overriding
the registerPropertyEditors(PropertyEditorRegistry) hook method. |
validator | null | The validator for this action. The validator must support the specified form object class. |
messageCodesResolver | null | Set the strategy to use for resolving errors into message codes. |
- Author:
- Erwin Vervaet, Keith Donald
- See Also:
-
PropertyEditorRegistrar
DataBinder
ScopeType
-
Nested Class Summary
Nested classes/interfaces inherited from class org.springframework.webflow.action.MultiAction
MultiAction.MethodResolver
-
Field Summary
Modifier and TypeFieldDescriptionstatic final String
The default form object name ("formObject").static final String
Optional attribute that identifies the method that should be invoked on the configured validator instance, to support piecemeal wizard page validation ("validatorMethod").Fields inherited from class org.springframework.webflow.action.AbstractAction
logger
-
Constructor Summary
ConstructorDescriptionBean-style default constructor; creates a initially unconfigured FormAction instance relying on default property values.FormAction
(Class<?> formObjectClass) Creates a new form action that manages instance(s) of the specified form object class. -
Method Summary
Modifier and TypeMethodDescriptionbind
(RequestContext context) Bind incoming request parameters to allowed fields of the form object.bindAndValidate
(RequestContext context) Bind incoming request parameters to allowed fields of the form object and then validate the bound form object if a validator is configured.protected org.springframework.validation.DataBinder
createBinder
(RequestContext context, Object formObject) Create a new binder instance for the given form object and request context.protected Object
createFormObject
(RequestContext context) Create the backing form object instance that should be managed by thisform action
.protected void
doBind
(RequestContext context, org.springframework.validation.DataBinder binder) Bind allowed parameters in the external context request parameter map to the form object using given binder.protected void
doValidate
(RequestContext context, Object formObject, org.springframework.validation.Errors errors) Validate given form object using a registered validator.protected org.springframework.validation.Errors
getFormErrors
(RequestContext context) Convenience method that returns the form object errors for this form action.Get the scope in which the Errors object will be placed.protected Object
getFormObject
(RequestContext context) Convenience method that returns the form object for this form action.protected FormObjectAccessor
getFormObjectAccessor
(RequestContext context) Factory method that returns a new form object accessor for accessing form objects in the provided request context.Class<?>
Return the form object class for this action.Return the name of the form object in the configured scope.Get the scope in which the form object will be placed.org.springframework.validation.MessageCodesResolver
Return the strategy to use for resolving errors into message codes.org.springframework.beans.PropertyEditorRegistrar
Get the property editor registration strategy for this action's data binders.protected org.springframework.webflow.action.DispatchMethodInvoker
Returns a dispatcher to invoke validation methods.org.springframework.validation.Validator
Returns the validator for this action.protected void
Action initializing callback, may be overridden by subclasses to perform custom initialization logic.protected void
initBinder
(RequestContext context, org.springframework.validation.DataBinder binder) Initialize a new binder instance.protected void
registerPropertyEditors
(org.springframework.beans.PropertyEditorRegistry registry) Register custom editors to perform type conversion on fields of your form object during data binding and form display.protected void
registerPropertyEditors
(RequestContext context, org.springframework.beans.PropertyEditorRegistry registry) Register custom editors to perform type conversion on fields of your form object during data binding and form display.resetForm
(RequestContext context) Resets the form by clearing out the form object in the specified scope and recreating it.void
setFormErrorsScope
(ScopeType errorsScope) Set the scope in which the Errors object will be placed.void
setFormObjectClass
(Class<?> formObjectClass) Set the form object class for this action.void
setFormObjectName
(String formObjectName) Set the name of the form object in the configured scope.void
setFormObjectScope
(ScopeType scopeType) Set the scope in which the form object will be placed.void
setMessageCodesResolver
(org.springframework.validation.MessageCodesResolver messageCodesResolver) Set the strategy to use for resolving errors into message codes.void
setPropertyEditorRegistrar
(org.springframework.beans.PropertyEditorRegistrar propertyEditorRegistrar) Set a property editor registration strategy for this action's data binders.setupForm
(RequestContext context) Prepares a form object for display in a new form, creating it and caching it in thegetFormObjectScope()
if necessary.void
setValidator
(org.springframework.validation.Validator validator) Set the validator for this action.toString()
validate
(RequestContext context) Validate the form object by invoking the validator if configured.protected boolean
validationEnabled
(RequestContext context) Return whether validation should be performed given the state of the flow request context.Methods inherited from class org.springframework.webflow.action.MultiAction
doExecute, getMethodResolver, setMethodResolver, setTarget
Methods inherited from class org.springframework.webflow.action.AbstractAction
afterPropertiesSet, doPostExecute, doPreExecute, error, error, execute, getActionNameForLogging, getEventFactorySupport, no, result, result, result, result, success, success, yes
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
Methods inherited from interface org.springframework.beans.factory.InitializingBean
afterPropertiesSet
-
Field Details
-
DEFAULT_FORM_OBJECT_NAME
The default form object name ("formObject").- See Also:
-
VALIDATOR_METHOD_ATTRIBUTE
Optional attribute that identifies the method that should be invoked on the configured validator instance, to support piecemeal wizard page validation ("validatorMethod").- See Also:
-
-
Constructor Details
-
FormAction
public FormAction()Bean-style default constructor; creates a initially unconfigured FormAction instance relying on default property values. Clients invoking this constructor directly must set the formObjectClass property or overridecreateFormObject(RequestContext)
.- See Also:
-
FormAction
Creates a new form action that manages instance(s) of the specified form object class.- Parameters:
formObjectClass
- the class of the form object (must be instantiable)
-
-
Method Details
-
getFormObjectName
Return the name of the form object in the configured scope. -
setFormObjectName
Set the name of the form object in the configured scope. The form object will be included in the configured scope under this name. -
getFormObjectClass
Return the form object class for this action. -
setFormObjectClass
Set the form object class for this action. An instance of this class will get populated and validated. This is a required property if you register a validator with the form action (setValidator(Validator)
)!If no form object name is set at the moment this method is called, a form object name will be automatically generated based on the provided form object class using
ClassUtils.getShortNameAsProperty(java.lang.Class)
. -
getFormObjectScope
Get the scope in which the form object will be placed. -
setFormObjectScope
Set the scope in which the form object will be placed. The default if not set isflow scope
. -
getFormErrorsScope
Get the scope in which the Errors object will be placed. -
setFormErrorsScope
Set the scope in which the Errors object will be placed. The default if not set isflash scope
. -
getPropertyEditorRegistrar
public org.springframework.beans.PropertyEditorRegistrar getPropertyEditorRegistrar()Get the property editor registration strategy for this action's data binders. -
setPropertyEditorRegistrar
public void setPropertyEditorRegistrar(org.springframework.beans.PropertyEditorRegistrar propertyEditorRegistrar) Set a property editor registration strategy for this action's data binders. This is an alternative to overriding theregisterPropertyEditors(PropertyEditorRegistry)
method. -
getValidator
public org.springframework.validation.Validator getValidator()Returns the validator for this action. -
setValidator
public void setValidator(org.springframework.validation.Validator validator) Set the validator for this action. When setting a validator, you must also set theform object class
. The validator must support the specified form object class. -
getMessageCodesResolver
public org.springframework.validation.MessageCodesResolver getMessageCodesResolver()Return the strategy to use for resolving errors into message codes. -
setMessageCodesResolver
public void setMessageCodesResolver(org.springframework.validation.MessageCodesResolver messageCodesResolver) Set the strategy to use for resolving errors into message codes. Applies the given strategy to all data binders used by this action.Default is null, i.e. using the default strategy of the data binder.
- See Also:
-
createBinder(RequestContext, Object)
DataBinder.setMessageCodesResolver(org.springframework.validation.MessageCodesResolver)
-
initAction
protected void initAction()Description copied from class:AbstractAction
Action initializing callback, may be overridden by subclasses to perform custom initialization logic.Keep in mind that this hook will only be invoked when this action is deployed in a Spring application context since it uses the Spring
InitializingBean
mechanism to trigger action initialisation.- Overrides:
initAction
in classAbstractAction
-
setupForm
Prepares a form object for display in a new form, creating it and caching it in thegetFormObjectScope()
if necessary. Also installs custom property editors for formatting form object values in UI controls such as text fields.A new form object instance will only be created (or more generally acquired) with a call to
createFormObject(RequestContext)
, if the form object does not yet exist in the configuredscope
. If you want to reset the form handling machinery, including creation or loading of a fresh form object instance, callresetForm(RequestContext)
instead.NOTE: This action method is not designed to be overridden and might become
final
in a future version of Spring Web Flow. If you need to execute custom form setup logic have your flow call this method along with your own custom methods as part of a single action chain.- Parameters:
context
- the action execution context, for accessing and setting data in "flow scope" or "request scope"- Returns:
- "success" when binding and validation is successful
- Throws:
Exception
- an unrecoverable exception occurs, either checked or unchecked- See Also:
-
bindAndValidate
Bind incoming request parameters to allowed fields of the form object and then validate the bound form object if a validator is configured.NOTE: This action method is not designed to be overridden and might become
final
in a future version of Spring Web Flow. If you need to execute custom bind and validate logic have your flow call this method along with your own custom methods as part of a single action chain. Alternatively, override thedoBind(RequestContext, DataBinder)
ordoValidate(RequestContext, Object, Errors)
hooks.- Parameters:
context
- the action execution context, for accessing and setting data in "flow scope" or "request scope"- Returns:
- "success" when binding and validation is successful, "error" if there were binding and/or validation errors
- Throws:
Exception
- an unrecoverable exception occurred, either checked or unchecked
-
bind
Bind incoming request parameters to allowed fields of the form object.NOTE: This action method is not designed to be overridden and might become
final
in a future version of Spring Web Flow. If you need to execute custom data binding logic have your flow call this method along with your own custom methods as part of a single action chain. Alternatively, override thedoBind(RequestContext, DataBinder)
hook.- Parameters:
context
- the action execution context, for accessing and setting data in "flow scope" or "request scope"- Returns:
- "success" if there are no binding errors, "error" otherwise
- Throws:
Exception
- an unrecoverable exception occured, either checked or unchecked
-
validate
Validate the form object by invoking the validator if configured.NOTE: This action method is not designed to be overridden and might become
final
in a future version of Spring Web Flow. If you need to execute custom validation logic have your flow call this method along with your own custom methods as part of a single action chain. Alternatively, override thedoValidate(RequestContext, Object, Errors)
hook.- Parameters:
context
- the action execution context, for accessing and setting data in "flow scope" or "request scope"- Returns:
- "success" if there are no validation errors, "error" otherwise
- Throws:
Exception
- an unrecoverable exception occured, either checked or unchecked- See Also:
-
resetForm
Resets the form by clearing out the form object in the specified scope and recreating it.NOTE: This action method is not designed to be overridden and might become
final
in a future version of Spring Web Flow. If you need to execute custom reset logic have your flow call this method along with your own custom methods as part of a single action chain.- Parameters:
context
- the request context- Returns:
- "success" if the reset action completed successfully
- Throws:
Exception
- if an exception occured- See Also:
-
getFormObject
Convenience method that returns the form object for this form action. If not found in the configured scope, a new form object will be created by a call tocreateFormObject(RequestContext)
and exposed in the configuredscope
.The returned form object will become the
current
form object.- Parameters:
context
- the flow execution request context- Returns:
- the form object
- Throws:
Exception
- when an unrecoverable exception occurs
-
getFormErrors
protected org.springframework.validation.Errors getFormErrors(RequestContext context) throws Exception Convenience method that returns the form object errors for this form action. If not found in the configured scope, a new form object errors will be created, initialized, and exposed in the confguredscope
.Keep in mind that an Errors instance wraps a form object, so a form object will also be created if required (see
getFormObject(RequestContext)
).- Parameters:
context
- the flow request context- Returns:
- the form errors
- Throws:
Exception
- when an unrecoverable exception occurs
-
createBinder
protected org.springframework.validation.DataBinder createBinder(RequestContext context, Object formObject) throws Exception Create a new binder instance for the given form object and request context. Can be overridden to plug in custom DataBinder subclasses.Default implementation creates a standard WebDataBinder, and invokes
initBinder(RequestContext, DataBinder)
andregisterPropertyEditors(PropertyEditorRegistry)
.- Parameters:
context
- the action execution context, for accessing and setting data in "flow scope" or "request scope"formObject
- the form object to bind onto- Returns:
- the new binder instance
- Throws:
Exception
- when an unrecoverable exception occurs- See Also:
-
doBind
protected void doBind(RequestContext context, org.springframework.validation.DataBinder binder) throws Exception Bind allowed parameters in the external context request parameter map to the form object using given binder.- Parameters:
context
- the action execution context, for accessing and setting data in "flow scope" or "request scope"binder
- the data binder to use- Throws:
Exception
- when an unrecoverable exception occurs
-
doValidate
protected void doValidate(RequestContext context, Object formObject, org.springframework.validation.Errors errors) throws Exception Validate given form object using a registered validator. If a "validatorMethod" action property is specified for the currently executing action, the identified validator method will be invoked. When no such property is found, the defualtvalidate()
method is invoked.- Parameters:
context
- the action execution context, for accessing and setting data in "flow scope" or "request scope"formObject
- the form objecterrors
- the errors instance to record validation errors in- Throws:
Exception
- when an unrecoverable exception occurs
-
getValidateMethodInvoker
protected org.springframework.webflow.action.DispatchMethodInvoker getValidateMethodInvoker()Returns a dispatcher to invoke validation methods. Subclasses could override this to return a custom dispatcher. -
getFormObjectAccessor
Factory method that returns a new form object accessor for accessing form objects in the provided request context.- Parameters:
context
- the flow request context- Returns:
- the accessor
-
createFormObject
Create the backing form object instance that should be managed by thisform action
. By default, will attempt to instantiate a new form object instance of typegetFormObjectClass()
transiently in memory.Subclasses should override if they need to load the form object from a specific location or resource such as a database or filesystem.
Subclasses should override if they need to customize how a transient form object is assembled during creation.
- Parameters:
context
- the action execution context for accessing flow data- Returns:
- the form object
- Throws:
IllegalStateException
- if thegetFormObjectClass()
property is not set and this method has not been overriddenException
- when an unrecoverable exception occurs
-
initBinder
Initialize a new binder instance. This hook allows customization of binder settings such as theallowed fields
,required fields
anddirect field access
. Called bycreateBinder(RequestContext, Object)
.Note that registration of custom property editors should be done in
registerPropertyEditors(PropertyEditorRegistry)
, not here! This method will only be called when a new data binder is created.- Parameters:
context
- the action execution context, for accessing and setting data in "flow scope" or "request scope"binder
- new binder instance- See Also:
-
registerPropertyEditors
protected void registerPropertyEditors(RequestContext context, org.springframework.beans.PropertyEditorRegistry registry) Register custom editors to perform type conversion on fields of your form object during data binding and form display. This method is called on form errors initialization anddata binder
initialization.Property editors give you full control over how objects are transformed to and from a formatted String form for display on a user interface such as a HTML page.
This default implementation will call the
simpler form
of the method not taking aRequestContext
parameter.- Parameters:
context
- the action execution context, for accessing and setting data in "flow scope" or "request scope"registry
- the property editor registry to register editors in- See Also:
-
registerPropertyEditors
protected void registerPropertyEditors(org.springframework.beans.PropertyEditorRegistry registry) Register custom editors to perform type conversion on fields of your form object during data binding and form display. This method is called on form errors initialization anddata binder
initialization.Property editors give you full control over how objects are transformed to and from a formatted String form for display on a user interface such as a HTML page.
This default implementation will simply call
registerCustomEditors
on thepropertyEditorRegistrar
object that has been set for the action, if any.- Parameters:
registry
- the property editor registry to register editors in
-
validationEnabled
Return whether validation should be performed given the state of the flow request context. Default implementation always returns true.- Parameters:
context
- the request context, for accessing and setting data in "flow scope" or "request scope"- Returns:
- whether or not validation is enabled
-
toString
-