About us
Contact us
Products
Services
Articles
 Twitter    Bookmark and Share

4. JavaBeans - HTML Forms Mapping

Contents | Previous Chapter | Next Chapter

This chapter describes the way form data is mapped to bean objects and bean objects are mapped to HTML forms. In other words, it explains what FormUtils.formToBean() and FormUtils.beanToForm() do.


4.1. Form-to-Bean Mapping

The formToBean() method of FormUtils takes a FormData instance, a bean object, an optional logger object, an optional string prefix and an optional Locale object. It iterates over the properties of the bean object and tries to set them to the values of the form parameters. It returns a Hashtable instance that contains the errors that occurred during the mapping process or null if no error occurred.

The FormData instance may be a ServletFormData object that delegates its methods to a javax.servlet.http.HttpServletRequest instance. The "Java Servlet Specification" states that HttpServletRequest can parse the form data only when the "application/x-www-form-urlencoded" media type is used.

The Servlet API does not support the "multipart/form-data" encoding type, which is necessary for file uploading. The com.devsphere.mapping.ServletFormData class can use the JavaMail's MIME multipart support to parse the input stream of the wrapped javax.servlet.http.HttpServletRequest. The parameter set may include strings, string arrays, FileBean objects and FileBean arrays.

If you want to use another encoding format, you'll have to parse the content of the request's input stream. You may still use Devsphere Mapping Framework by implementing the methods of the FormData abstract class on top of your form data parser.

The class of the bean object must meet the requirements described in a previous chapter.

The optional logger object provides a mechanism for logging the mapping errors. The com.devsphere.logging package contains a few concrete implementations of the AbstractLogger class. ServletLogger delegates its methods to javax.servlet.ServletContext, PrintLogger wraps java.io.PrintStream and CompoundLogger may be used to redirect the logging operations to two other loggers. You may implement your own loggers if necessary.

If the optional prefix parameter is not present, the names of the parameters must be the same as the names of the bean properties. Otherwise, the names of the parameters are expected to start with the prefix, followed by a dot and the property names.

The optional Locale object is used to load the optional bean properties that may contain default values, error messages and other information that helps controlling and customizing the mapping process.

As you already know from previous chapters, the mapping utilities separate the bean properties in four categories: standard properties, standard indexed properties, contained data beans and contained bean arrays.


4.1.1. Mapping to a standard property

For each standard property, formToBean()

  • calls the getParameter() method of the FormData instance, passing as parameter "prefix.propertyName" or just "propertyName" if the optional prefix is not present,
  • tries to convert the returned string to the property's type and
  • sets the value of the property.

If the parameter is missing or the conversion of the string fails then a MappingError object is added to the error table and the property is set to its default value.

Boolean properties have a special treatment. They are set to false if the parameter is missing or its value is "false". Otherwise, the value is set to true. No error is signaled if the parameter value is missing. This behavior makes possible the use of the boolean properties with the checkbox buttons of the HTML forms.

Note: The standard properties include strings, primitives, primitive wrappers, BigInteger and BigDecimal.


4.1.2. Mapping to a standard indexed property

For each standard indexed property, formToBean()

  • calls the getParameterValues() method of the FormData instance, passing as parameter "prefix.propertyName" or just "propertyName" if the optional prefix is not present,
  • tries to convert the strings of the returned array and
  • sets the values of the indexed property. (note: All these values become the elements of a new array that is stored to the indexed property using the setter method.)

Any mapping error is stored in the error table. If there are multiple errors, the error table will use a vector of MappingError objects.

Note: The standard indexed properties include string arrays, primitive arrays, wrapper arrays, BigInteger[] and BigDecimal[].


4.1.3. Mapping to a contained data bean

For each contained data bean (whose type isn't FileBean), formToBean()

  • creates a new instance of the contained bean by calling the no-arg constructor,
  • computes a sub-prefix by adding a dot ('.') and the property name (subBean) to the optional prefix, which is an empty string by default,
  • passes the contained bean instance and the sub-prefix ("prefix.subBean" or just "subBean") to a recursive call of formToBean(), and
  • sets the subBean property of the bean object to the newly created object.

Note: All recursive calls of formToBean() get the same FormData instance, share the same error table and use the same logger and Locale objects that are passed to the initial formToBean() call.

A PointBean object that is mapped to an image map is treated as a regular contained bean, i.e. the subBean.x and subBean.y parameters are mapped to the x and y properties of the PointBean object.

For properties whose type is FileBean, formToBean()

  • calls the getFileParameter() method of the FormData instance, passing as parameter "prefix.subBean" or just "subBean" if the optional prefix is not present.
  • sets the subBean property of the bean object to the FileBean instance returned by getFileParameter().

4.1.4. Mapping to a contained bean array

For each contained bean array (whose type isn't FileBean[]), formToBean()

  • gets the array's length, by looking first for a FIXED_LENGTH.subBeanArray bean resource. If this resource isn't found, it looks for a subBeanArray.length parameter,
  • creates a new array with the obtained length,
  • creates a bean instance for each array element and passes it together with a sub-prefix (prefix.subBeanArray.index or just subBeanArray.index) to a recursive call of formToBean(),
  • sets the subBeanArray property of the bean object to the newly created array.

For properties whose type is FileBean[], formToBean()

  • calls the getFileParameterValues() method of the FormData instance, passing as parameter "prefix.subBeanArray" or just "subBeanArray" if the optional prefix is not present.
  • sets the subBeanArray property of the bean object to the FileBean array returned by getFileParameterValues().

4.2. Bean-to-Form Mapping

The beanToForm() method of FormUtils takes a bean instance, a Hashtable that may contain mapping errors, a FormDocument object, an optional form name, an optional logger object, an optional string prefix and an optional Locale object. The values of the properties are stored as the default values of the document's form elements. The error table may be null or it must be a Hashtable returned by one of the mapping utilities of the framework. The error messages extracted from the error table are inserted into the document. After mapping, the content of the document can be sent in HTML format.

The beanToForm() method maps a bean property to all form elements that have the same name, if the optional prefix parameter is not provided. Otherwise, the names of the form elements are expected to start with the prefix, followed by a dot and the property names.

Supposing that beanToForm() gets the value of a property, which must be inserted as the default value of a form element, there are several cases:

  • If the form element is defined by an <INPUT> tag then
  • If the type of the form element is TEXT, TEXTAREA or HIDDEN then the value of the bean property is converted to String and inserted as the value of the VALUE attribute of the form element.
  • If the type of the form element is CHECKBOX or RADIO then
    • the mapping method inserts the attribute CHECKED within the <INPUT> tag if the bean property is boolean and its value is true.
    • If the type of the bean property is not boolean (or Boolean) then its value is converted to String. The attribute CHECKED is inserted only if the resulted String is equal to the value of the VALUE attribute of the form element.
    • The attribute CHECKED will not be present in any other case.
  • Nothing is done if the type of the form element is BUTTON, SUBMIT, RESET, IMAGE, FILE or PASSWORD.
  • If the form element is defined by a <TEXTAREA> tag then the default value is inserted right after that tag.
  • If the form element is defined by a <SELECT> tag then the SELECTED attribute is inserted within the <OPTION> tag whose value is equal to the property's value.
  • If another tag defines the form element then no action is performed.

By default, an error messages is inserted just above the associated form element or group of form elements. The insertion place can be changed by relocating the ERROR_MESSAGE variables as it was described in a previous chapter.


4.2.1. Mapping a standard property

A standard property can be mapped to one or more form elements that have the same name (preceded by the optional prefix).

For 1-1 mapping (single value property - single form element), beanToForm()

  • inserts the default value of the form element as described above, and
  • inserts the error message, if any, within the document that contains the form

For example, a standard property (String, int, float, etc) could be mapped to a TEXT input element or to a list defined with <SELECT>. A boolean property could be mapped to a CHECKBOX.

For 1-n mapping (single value property - multiple form elements with the same name), beanToForm()

  • sets the default value of all form elements to the value of the property, and
  • inserts the error message once (by default just before the first element)

For example, a String or Integer could be mapped to a group of RADIO buttons. The CHECKED attribute will be inserted only for that button whose VALUE is equal to the property value.


4.2.2. Mapping a standard indexed property

A standard indexed property can be mapped to one or more form elements that have the same name (preceded by the optional prefix).

For n-1 mapping (indexed property - single form element), beanToForm()

  • converts the values of the indexed property to strings and stores them to a string array (this step is skipped if the value of the property is already a string array),
  • sets the default value of the form element to the obtained string array, and
  • concatenates and inserts all error messages (by default just before the form element)

In this case, the form element is expected to be a list that allows the selection of multiple items. The elements of the String array are the items that must be selected.

For n-m mapping (indexed property - multiple form elements with the same name), beanToForm()

  • sets the default value of each form element to the corresponding value of the indexed property (i.e. the first form element gets the property value whose index is 0, the second form element gets the property value whose index is 1, and so on),
  • the error messages are inserted just before those form elements that may have caused them.

If n < m, some form elements won't have default values. If n > m, some property values will not be stored to any form element. No error is signaled.

For example, an indexed property whose type is int[] could be mapped to a group of text fields. Suppose that the user filled partially the form and sent the data. A formToBean() call got the form data and tried to set the bean property, storing "missing data", "number format error" and any other mapping errors to a Hashtable. The beanToForm() call will have to set the default values of those form elements whose data was valid. The form elements whose data wasn't valid will get a default value too and the incorrect value inputted by the user will be ignored. All error messages will be inserted just above those form elements that caused the errors.

The n-m mapping is treated differently if the form elements are CHECKBOX buttons. The CHECKED attribute is inserted to all elements whose VALUE is equal to one of the property values. This way, it is possible to use a group of checkboxes instead of a <SELECT> element that has the attribute MULTIPLE.


4.2.3. Mapping a contained bean

For a contained data bean (whose type is neither PointBean nor FileBean), beanToForm()

  • computes a sub-prefix by adding a dot ('.') and the property name (subBean) to the optional prefix, which is an empty string by default,
  • passes the contained bean instance and the sub-prefix (prefix.subBean or just subBean) to a recursive call of beanToForm().

The same form must contain elements for all properties of the main bean, for all properties of the contained beans, for all properties of the contained beans of the contained beans and so on.

Note: All recursive calls of beanToForm(), share the same error table, get the same document and form name, and use the same logger and Locale objects that are passed to the initial beanToForm call.

The values of the properties of PointBean and FileBean aren't mapped to any form elements. However, any error messages related to the associated image map or file element are inserted within the form document.


4.2.4. Mapping a contained bean array

For a contained bean array (whose type is neither PointBean[] nor FileBean[]), beanToForm()

  • stores the array's length to the form element named subBeanArray.length, if such an element exists and there is no bean resource named FIXED_LENGTH.subBeanArray. (The form element isn't necessary if the FIXED_LENGTH.subBeanArray resource is used.) and
  • each array element is passed together with a sub-prefix (prefix.subBeanArray.index or just subBeanArray.index) to a recursive call of beanToForm().

A FileBean array is supposed to be associated with a list of FILE input elements. The user is expected to select one or more files. An error message is signaled if the property isn't optional and the user selects no files.


4.3. Hints and Tips

A previous chapter presents the HTML forms and the data beans.

Typical mappings include:

  • standard property - TEXT / TEXTAREA / PASSWORD / HIDDEN
  • standard indexed property - TEXT[] / TEXTAREA[] / PASSWORD[] / HIDDEN[]
  • boolean property - CHECKBOX
  • standard indexed property - CHECKBOX[]
  • standard property - RADIO[]
  • standard property / standard indexed property - SELECT
  • standard property - SUBMIT[]
  • PointBean - IMAGE
  • FileBean - FILE
  • FileBean[] - FILE[]

Some of the form elements cannot have a default value; they only provide a user value for a bean property. These elements are:

  • SUBMIT
  • IMAGE
  • FILE
  • PASSWORD

If a form has two or more SUBMIT buttons, you can give them the same NAME and different labels (the VALUE attributes). Map these buttons to a standard property (usually a String) and use this property to find out which SUBMIT button was clicked. One of the examples does this.

Contents | Previous Chapter | Next Chapter

Copyright © 2000-2009 Devsphere

About us
Contact us
Products
Services
Articles