Class Form
Method in this class are thread safe since form processing is done
entirely within various methods and the form processing results in the
creation of seperate FormData objects for each request.
Various Fields can be added to the form at form creation
time. Some fields (like Hidden can also be added per user/request,
dynamically, to the FormData object. This is useful while saving
some user or request specific information.
A form collects data from the front-end/web-client and often saves it to a back end database entity. Form data validation can be done in 2 ways:
- at the form level where the form collects data and validates it via validators associated with the form object.
- at the field level where the form itself does no higher level validation but populates a field and then asks that field to validate itself.
An HTML form presented to the user can contain fields from more than 1 database table. For example, there could to 2 database tables, say "person" and "office" both with a "other" column. Since each field contained in the form object must have a unique name, there will be a name clash between the fields/attributes of the entities when 2 fields with the name "other" are added to the form.
There are 2 general approaches to solving this problem.
- Seperate database tables should be represented by seperate Form objects (all of which can be rendered in the same HTML document shown to the user). Different instances of form objects (say 1 per table) act as seperate name-spaces and fields having the same name can exist in these seperate instances. However, the dynamic server page where the form object is rendered/submitted has to obtain these seperate instances from the application object (or wherever all forms are stored) -- which adds some complexity.
- Create 1 instance of a form object containing fields from more than one table. In this case, some or all field names can be prepended (or suffixed) with the name of the database table. This removes any name clashes if done only for clashing fields; if done for every field may help in documenting which table that field belongs to. There is more typing involved with this approach.
Sometimes, other methods need to obtain a field (for a particular table) by
name. For example, the managers generated by Generate
have a addValidators(form) method that extract the fields for a
particular table and add validators to that field. This method in
particular need to be passed either the appropriate form object in which
that field exists (if there are multiple form objects) or in the case of
only 1 form object, passed the prefix for that particular field, if that
field was added with a prefix to it's name.
-
Field Summary
Fields -
Constructor Summary
ConstructorsConstructorDescriptionCreates a new form with the specified name, method=POST and no action URLCreates a new form with logging to the default log retreived byLog.getDefault()and the defaultSubmitHackedHandlerCreates a new form with the specified name, method (get/post) and URL -
Method Summary
Modifier and TypeMethodDescriptionadd(Dependency d) Adds the specified dependency to the form.Adds the specified element to the form.Adds aFieldRefto this Form.voidaddDynamicField(FormData fd, Hidden f) Adds aHiddenfield to this form.voidConvenience method that invokesaddErrorwith an empty validation errorKey.voidAdds a form level validation error message.voidaddMessage(FormData fd, String key, String value) Adds an arbitrary message for this request.voidvoidaddValidator(FormValidator validator) Adds a form level validator to this form.booleancontainsField(String fieldName) Returns true if the form contains the specified field.voiddestroy()This method should be called when the form is removed from session or application scope.Returns the form field with the specified name.Returns the action URL string.Returns a collection view of all the fields contained in this form.getCheckbox(String name) Returns the field with the specific name as aCheckbox.getCheckboxGroup(String name) Returns the field with the specific name as aCheckbox.getContaining(String name) Returns all the fields that contains the specified name.Returns the display URL string.getDynamicField(FormData fd, String fieldName) Gets aHiddenfield added to the form data object.getFieldRef(String key) Returns theFieldRefwith the specified key.getFormErrorsFor(FormData fd, String formValidatorName) Returns a list containing all form-level errors for the specified validator.Returns the field with the specific name as aHidden.getMessage(FormData fd, String key) Retrieves a previously added message or null if the speccified form data was null or if the message was not found.getName()Returns the name of this formgetPassword(String name) Returns the field with the specific name as aPassword.Returns the field with the specific name as aRadio.getRadioGroup(String name) Returns the field with the specific name as aCheckbox.Returns the field with the specific name as aSelect.getSubmittedField(jakarta.servlet.http.HttpServletRequest req, String name) Once the form is displayed to the user (with, say, hidden fields that were added dynamically for that request), then when that form is submitted, those dynamic fields can be retrieved via any of: theServletRequest.getParameter(String)method (often the easiest way) themethod (which will attempt to read the request parameter with the specified name and return is as a Hidden field.invalid reference
#getSubmittedField(HttpServletRequest)Returns the field with the specific name as aText.getTextArea(String name) Returns the field with the specific name as aTextArea.getTimer()getUpdatableSelect(String name) Returns the field with the specific name as aRefreshableSelect.handleSubmit(jakarta.servlet.http.HttpServletRequest req) Processes the submitted form.handleSubmit(jakarta.servlet.http.HttpServletRequest req, Connection con) This method is similar tohandleSubmit(jakarta.servlet.http.HttpServletRequest)except it stores the specified connection in the form data.static booleanReturns true if validation did not succeed.refresh(jakarta.servlet.http.HttpServletRequest req) refresh(jakarta.servlet.http.HttpServletRequest req, Connection con) Refreshes the form for this request by running all attached refreshers and dependencies.Removes the specified field from the form.voidrenderDynamicFields(FormData fd, Writer out) Renders all dynamically added hidden fields of the form.voidrenderError(FormData fd, Writer writer) Convenience method to render form-level validation errors.voidrenderErrorFor(FormData fd, Writer writer, String formValidatorName) Convenience method to render a validation error for a particluar form level validator.voidsetActionURL(String url) Sets an arbitrary application specific string that can later be retrieved.voidsetDisplayURL(String url) Sets an arbitrary application specific string.toString()
-
Field Details
-
empty_list
-
empty_map
-
-
Constructor Details
-
Form
-
Form
-
Form
Creates a new form with logging to the default log retreived byLog.getDefault()and the defaultSubmitHackedHandler -
Form
-
-
Method Details
-
destroy
This method should be called when the form is removed from session or application scope. It is very important to do this if there are background update tasks because this method stops such background refresh timer thread (which would otherwise continue to run). -
remove
Removes the specified field from the form. SeeMap.remove(Object)for the general contract.- Parameters:
field- the field to remove from the form.
-
add
Adds the specified element to the form. The added field can later be retrieved via it's name. The field iteration order will be the same order in which fields are added via this method.Note, field names have to be unique. "Grouped" fields (such as HTML form checkboxes or radio buttons) which require the same field name are encapsulated by a single appropriate grouped field object such as
RadioGroupandCheckboxGroup. This field object itself should have a unique name.- Returns:
- A reference to this form as a convenience for method chaining
- Throws:
IllegalArgumentException- if an element with the same name already exists in this form.
-
add
Adds the specified dependency to the form. -
add
-
addError
Adds a form level validation error message. This method is needed when form level validation is done via classes that are not subclasses ofFormValidator(these classes are used outside of the validation framework and their error message still needs to be added to the form data).This is a very useful method for adding the results of arbitrary code to this form.
- Parameters:
fd- form dataerrorKey- an arbitrary/optional validation key which allows to later retrieve and display a particular form error. Specify null for no key.errorMessage- the form error message- See Also:
-
addError
-
addDynamicField
Adds aHiddenfield to this form. This field exists only for the duration of this form data object and is useful for request specific data. -
addValidator
Adds a form level validator to this form. Note, validator names have to be unique and not clash with other form level validator names.- Throws:
IllegalArgumentException- if a validator with the same name already exists in this form.
-
addMessage
Adds an arbitrary message for this request. Messages can include arbitrary warnings, usage help etc. -
containsField
Returns true if the form contains the specified field. -
getMessage
Retrieves a previously added message or null if the speccified form data was null or if the message was not found. -
addSubmitHackedHandler
-
handleSubmit
public FormData handleSubmit(jakarta.servlet.http.HttpServletRequest req) throws jakarta.servlet.ServletException, IOException Processes the submitted form. This method must be called after each form submission by the servlet or page code that handles form submits. This method does the following:- populates the fields of the form from the submitted request.
- if the form has any dependencies and if the dependencies need updating, then those dependencies are updated. Validation is not carried out in this case since the form has changed and the user needs to typically carry out some other action before submitting the form.
- if there are no updated dependencies, validates the form via any validators attached to the form and it's fields.
hasError(fc.web.forms.FormData)method with the formdata returned by this method. Seeing validation errors is optional of course, and so is using validators in the first place.- Parameters:
req- the HttpServletRequest corresponding to the request being processed by this form.- Returns:
- a
FormDataobject containing populated field data and the results of the validation. - Throws:
jakarta.servlet.ServletExceptionIOException
-
handleSubmit
public FormData handleSubmit(jakarta.servlet.http.HttpServletRequest req, Connection con) throws jakarta.servlet.ServletException, IOException This method is similar tohandleSubmit(jakarta.servlet.http.HttpServletRequest)except it stores the specified connection in the form data. This connection can be used by any attached dependency classes for database queries when updating form depedencies.Note, we can set arbitrary objects in the
HttpServletRequestvia it'smethod. However, specifying and storing the connection in the FormData is easier to remember and use.invalid reference
setAttributeThere are 2 cases:
- The dependent fields (if any) will internally use
to obtain a connection and no connection has to be set in the form data.
invalid reference
WebApp#getConnection
The - The dependent fields (if any) classes will expect a connection in the form data. In that case, this method should be invoked.
handleSubmit(jakarta.servlet.http.HttpServletRequest)can then be used.handleSubmit(jakarta.servlet.http.HttpServletRequest)is sufficient.- Parameters:
req- the HttpServletRequest corresponding to the request being processed by this form.con- a connection object. The connection is not closed and it is the callers responsiblity to do so.- Throws:
jakarta.servlet.ServletExceptionIOException
- The dependent fields (if any) will internally use
-
refresh
public FormData refresh(jakarta.servlet.http.HttpServletRequest req) throws jakarta.servlet.ServletException, IOException - Throws:
jakarta.servlet.ServletExceptionIOException
-
refresh
public FormData refresh(jakarta.servlet.http.HttpServletRequest req, Connection con) throws jakarta.servlet.ServletException, IOException Refreshes the form for this request by running all attached refreshers and dependencies. Maintains form state. Does not run any validatators. Useful for re-displaying a form when lookup fields have changed in the database.To refresh the form for all users/requests from this point onwards, create a new instance of the form and replace the existing instance of the form with the newly created instance.
- Throws:
jakarta.servlet.ServletExceptionIOException
-
hasError
-
renderError
Convenience method to render form-level validation errors. This method writes validation error message for the specified form level validator. The error messages are encapulated in a html <div> tag and the class of this tag is set to form-errmsg. Each error message within this div is assigned it's own div with class set to form-errmsg-item- Parameters:
writer- the Writer to render errors to- Throws:
IOException
-
renderErrorFor
Convenience method to render a validation error for a particluar form level validator. The error messages are encapulated in a html <div> tag and the class of this tag is set to form-errmsg.- Parameters:
writer- the Writer to render errors toformValidatorName- the name of a form level validator- Throws:
IOException
-
getFieldErrors
- Parameters:
fd- a non-null form data object- Returns:
- a map containing field names as keys and the
field's validation error as the value. The data
type of each value is that returned by the
Field.getValidateErrors(FormData)method
-
getFormErrorsCollection
- Parameters:
fd- a non-null form data object- Returns:
- a list containing form level errors. The data type
of each value is that returned by the
FormValidator.getErrorMessage()method
-
getFormErrorsFor
Returns a list containing all form-level errors for the specified validator. If there are no errors for the specified validator, returns an empty list.- Parameters:
fd- a non-null form data objectformValidatorName- a form validator name
-
renderDynamicFields
Renders all dynamically added hidden fields of the form. Dynamic fields are created/ added per user per submit to theFormDataif/as needed.Note: Dynamic fields are not part of a form's fields and are not available via
- Throws:
SQLExceptionIOException
-
getName
-
setActionURL
Sets an arbitrary application specific string that can later be retrieved. Some applications may find this method useful. -
getActionURL
Returns the action URL string. Returns null if no url has been set. -
setDisplayURL
Sets an arbitrary application specific string. Intended to store the URL to the jsp or front end page that will render this form for the user. -
getDisplayURL
Returns the display URL string. Returns null if no display url has been set. -
getAllFields
Returns a collection view of all the fields contained in this form. -
get
-
getDynamicField
Gets aHiddenfield added to the form data object. Returns null if the form data object is null or if the specified field does not exist. Dyanamic fields returned by this method are only available for the duration of the form data object and can not obtain a field from a submitted form. (usefor that purpose.invalid reference
getDynamicField(FormData, HttpServletRequest) -
getSubmittedField
Once the form is displayed to the user (with, say, hidden fields that were added dynamically for that request), then when that form is submitted, those dynamic fields can be retrieved via any of:- the
ServletRequest.getParameter(String)method (often the easiest way) - the
method (which will attempt to read the request parameter with the specified name and return is as a Hidden field. (this is slightly more convenient if there is more than 1 hidden field with the same name, since all hidden fields with the same name are encapsulated by one object of type
invalid reference
#getSubmittedField(HttpServletRequest)Hidden).
- the
-
getContaining
Returns all the fields that contains the specified name. This is useful when a bunch of fields are created via database lookup tables (and each such field is prefixed/suffixed by say lookup_name + some number).- Parameters:
name- the name of the field- Returns:
- a List containing fields with matching names or or an empty list if no elements containing that name were found in this form.
-
getFieldRef
Returns theFieldRefwith the specified key. This is used to retrieve an arbitrary object added the viamethod. Returns null if no object is found for the specified key.invalid reference
#addObject -
getTimer
-
getSelect
Returns the field with the specific name as aSelect.- Throws:
IllegalArgumentException- if a field with the specified name does not exist or if the field exists but is not of type Select
-
getUpdatableSelect
Returns the field with the specific name as aRefreshableSelect.- Throws:
IllegalArgumentException- if a field with the specified name does not exist or if the field exists but is not of type RefreshableSelect
-
getCheckbox
Returns the field with the specific name as aCheckbox.- Throws:
IllegalArgumentException- if a field with the specified name does not exist or if the field exists but is not of type Checkbox
-
getCheckboxGroup
Returns the field with the specific name as aCheckbox.- Throws:
IllegalArgumentException- if a field with the specified name does not exist or if the field exists but is not of type Checkbox
-
getHidden
Returns the field with the specific name as aHidden.- Throws:
IllegalArgumentException- if a field with the specified name does not exist or if the field exists but is not of type Hidden
-
getText
Returns the field with the specific name as aText.- Throws:
IllegalArgumentException- if a field with the specified name does not exist or if the field exists but is not of type Text
-
getTextArea
Returns the field with the specific name as aTextArea.- Throws:
IllegalArgumentException- if a field with the specified name does not exist or if the field exists but is not of type TextArea
-
getPassword
Returns the field with the specific name as aPassword.- Throws:
IllegalArgumentException- if a field with the specified name does not exist or if the field exists but is not of type Password
-
getRadio
Returns the field with the specific name as aRadio.- Throws:
IllegalArgumentException- if a field with the specified name does not exist or if the field exists but is not of type Radio
-
getRadioGroup
Returns the field with the specific name as aCheckbox.- Throws:
IllegalArgumentException- if a field with the specified name does not exist or if the field exists but is not of type Checkbox
-
toString
-