Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

WebWork has one of Struts Action 2 offers advanced type conversion abilities, perhaps the most advanced type conversion abilities facilities available in any web-based framework in any Java language. Generally, you don't need to do anything to take advantage of ittype conversion, other than name your give HTML inputs names that can be used in OGNL expressions. (HTML inputs are form elements and other GET/POST parameters.) names that are valid OGNL expressions.

A Simple Example

Wiki Markup
{snippet:id=javadoc|javadoc=true|url=com.opensymphony.xwork.util.XWorkConverter}
Note
Wiki Markup
{snippet:id=i18n-note|javadoc=true|url=com.opensymphony.xwork.util.XWorkConverter}

WebWork The framework ships with a base helper base class that makes converting to and from Strings very easy. The class is comorg.apache.opensymphonystruts.webworkaction2.util.WebWorkTypeConverterStrutsTypeConverter. This helper class makes it very easy for you to write type converters that handle converting objects to Strings as well as from Strings. From the JavaDocs for this class:

Wiki Markup
{snippet:id=javadoc|javadoc=true|url=com.opensymphony.webwork.util.WebWorkTypeConverter}

...

The best way to take advantage of WebWorkthe framework's type conversion is to utilize complete objects (ideally your domain objects directly), rather than submitting . There is no need to capture form values on to using intermediate Strings and primitives and strings in your action and then converting convert those values to full objects in the execute() an Action method. Some tips for achieving this areHere are some tips for leveraging the framework's type conversion capabilties:

  • Use complex OGNL expressions - WebWork the framework will automatically take care of creating the actual objects for you.
  • Use JavaBeans! WebWork The framework can only create objects for you if your the objects obey the JavaBean specification and provide no-arg constructions, as well as getters and setters where appropriate.
  • Remember that person.name will call getPerson().setName(), but if you are expecting WebWork in order for the framework to create the Person object for you, a setPerson() must also exist.
  • Wiki Markup
    For lists and maps, use index notation, such as _people\[0\].name_ or _friends\['patrick'\].name_. Often these HTML form elements are being rendered inside a loop,. soFor you can[JSP Tags], use the iterator tag's status attribute if you're using. For [JSPFreeMarker Tags], oruse the special property $\{foo_index\} special property if you're using [FreeMarker Tags].
  • FOr For multiple select boxes, you obviously canit isn't possible to use index notation to name each individual item using index notation. Instead, name your element simply people.name and WebWork the framework will understand that it should create a new Person object for each selected item and set it's its name accordingly.

Advanced Type Conversion

WebWork The framework also has some very advanced, yet easy-to-use, type conversion features. Null property handling will automatically create objects where null references are found. Collection and map support provides intelligent null handling and type conversion for Java Collections. Type conversion error handling provides an easy a simple way to distinguish the difference between an input validation problem from and an input type conversion problem.

Null Property Handling

...

Collection and Map Support

WebWork The framework supports ways to determine discover the object type found for elements in collectionsa collection. This The discover is done made via an ObjectTypeDeterminer. The A default implementation is provided with the framework. The JavaDocs explain how map and colelction collection support is determined discovered in the DefaultObjectTypeDeterminer:

Wiki Markup
{snippet:id=javadoc|javadoc=true|url=com.opensymphony.xwork.util.DefaultObjectTypeDeterminer}

Additionally, you can create your own custom ObjectTypeDeterminer by implementing the ObjectTypeDeterminer interface. There is also an optional ObjectTypeDeterminer that utilizes Java 5 generics. See the J2SE 5 Support page for more information.

Indexing a collection by a property of that collection

It is also possible using webwork to get obtain a unique element of a collection , by passing the value of a given property of that element. By default, the property of the element of the collection is determined in Class-conversion.properties using KeyProperty_xxx=yyy, where xxx is the property of the bean 'Class' that returns the collection and yyy is the property of the collection element that we want to index on. Here is

For an example with , see the following two classes:

Code Block
titleMyAction.java
borderStylesolid


/**
 * @return a Collection of Foo objects
 */
public Collection getFooCollection()
{
    return foo;
}
Code Block
titleFoo.java
borderStylesolid


/**
 * @return a unique identifier
 */
public Long getId()
{
    return id;
}

Then put To enable type conversion, put the instruction KeyProperty_fooCollection=id in my the MyAction-conversion.properties file. This would allow to the technique allows use of the idiom fooCollection(someIdValue) to get obtain the Foo object with value someIdValue in the Set fooCollection. For example, fooCollection(22) would return the Foo object in the fooCollection collection whose id property value was 22.

This technique is useful, because it ties a collection element directly to its unique identifier and therefore does not force you . You are not forced to use an index and thus allows you to . You can edit the elements of a collection associated to a bean without any additional codecoding. For example, parameter name fooCollection(22).name and value Phil would set name the Foo object in the fooCollection collection whose id property value was 22 to be Phil.

Webwork  The framework automatically converts the type of the parameter sent in to the type of the key property using type conversion.

Wiki Markup
Unlike Map and List element properties, if fooCollection(22) does not exist, it will not be created. To do that If you would like it created, use the notation *fooCollection.makeNew\[index\]* where index is an integer 0, 1, and so on. Thus, parameter value pairs *fooCollection.makeNew\[0\]=Phil* and *fooCollection.makeNew\[1\]=John* would add two new Foo objects to fooCollection \-\- one with name property value Phil and the other with name property value Bar. Note, however, thatHowever, in the case of a Set, the {{equals}} and {{hashCode}} methods should be defined such that they don't only include the {{id}} property. That will cause one element of the null {{id}} propertiedproperties Foos to be removed from the Set.

...

Here is the model bean used within the list.
The KeyProperty for this bean is the id attribute.

Code Block
titleMyBean.java
borderStylesolid
public class MyBean implements Serializable {

    private Long id;
    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    public String toString() {
        return "MyBean{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

The action Action has a beanList attribute initialized with an empty ArrayList.

Code Block
titleMyBeanAction.java
borderStylesolid
ublicpublic class MyBeanAction implements Action {

    private List beanList = new ArrayList();
    private Map beanMap = new HashMap();

    public List getBeanList() {
        return beanList;
    }

    public void setBeanList(List beanList) {
        this.beanList = beanList;
    }

    public Map getBeanMap() {
        return beanMap;
    }

    public void setBeanMap(Map beanMap) {
        this.beanMap = beanMap;
    }

    public String execute() throws Exception {
        return SUCCESS;
    }
}

These conversion.properties tell the TypeConverter to use MyBean instances as elements of the List.

Code Block
titleMyBeanAction-conversion.properties
borderStylesolid
KeyProperty_beanList=id
Element_beanList=MyBean
CreateIfNull_beanList=true
  • When submitting this via a form, the

...

  • id

...

  • value is used as KeyProperty for the MyBean instances in the beanList.
  • Wiki Markup
    Notice the () notation\! Do not use \[\] notation,

...

  •  which is for Maps only\!
  • The value for name will be set to the MyBean instance with this special id.
  • The List does

...

  • not have null values added for unavailable id values.

...

  • This approach avoids the risk of OutOfMemoryErrors!
Code Block
titleMyBeanAction.jsp
borderStylesolid
<ww:iterator value="beanList" id="bean">
  <ww:textfield name="beanList(%{bean.id}).name" />
</ww:iterator>

...

There are two ways the error reporting can occur:

  1. globallyGlobally, using the Conversion Error Interceptor
  2. on On a per-field basis, using the conversion validator

By default, the conversion interceptor is included in webwork struts-default.xml in the default stack, so if you don't want . To keep conversion errors from reporting globally, you'll need to change the interceptor stack, and add additional validation rules.