Home

This Chapter
-Chapter 4: Input Validation and Data Conversion
-Data Types for Your Action Form’s Properties
-Input Validation and Data Conversion Example
-Using BeanUtils
-Efficient Conversion
-Summary

Table of Contents
-Introduction
-Chapter 1: Model 2 and Struts
-Chapter 2: Input Validation with Action Forms
-Chapter 3: The HTML Tag Library
-Chapter 4: Input Validation and Data Conversion
-Chapter 5: The Validator Plugin
-Chapter 6: The Expression Language
-Chapter 7: JSTL
-Chapter 8: The Bean Tag Library
-Chapter 9: The Logic Tag Library
-Chapter 10: Struts-EL, Nested, selectLabel
-Chapter 11: Message Handling and Internationalization
-Chapter 12: The Tiles Framework
-Chapter 13: Securing Struts Applications
-Chapter 14: The Config Object
-Chapter 15: The Persistence Layer
-Chapter 16: Object Caching
-Chapter 17: File Upload and File Download
-Chapter 18: Paging and Sorting
-Chapter 19: Preventing Double Submits
-Chapter 20: Early HttpSession Invalidation
-Chapter 21: Decorating Request Objects
-Chapter 22: How Struts Works

Previous
Next

 

Using BeanUtils

The action class in the app04a application has shown that there is a need for copying the values from one JavaBean (the action form OrderForm) to another (the transfer object OrderTO). A popular utility class named BeanUtils can help with JavaBeans copying. This class is available for free from the Apache Jakarta website, under the Commons project. You can download BeanUtils from this link.

http://jakarta.apache.org/commons/.

The BeanUtils class is part of the BeanUtils component. The class’s static copyProperties method can be used to copy a JavaBean’s properties to another JavaBean. The signature of this method is as follows:

public static void copyProperties(Object destination, Object origin);

Using introspection, the method loops through all the properties in origin. For each property, the method checks if there is a property having the same name in destination. If there is, the value of the property is copied to the destination. On the way, some data conversion is done. BeanUtils can convert strings to primitive values and vice versa. Internally, BeanUtils uses the org.apache.commons.beanutils.ConvertUtils class to convert data.

The ConvertUtils class cannot handle dates by default, because there is no available converter for converting a string to a java.util.Date. Luckily, ConvertUtils allows you to create your own converter and register your converter with it. Once you register a custom converter, you can use it for as long as the ConvertUtils instance is in memory.

To create a converter, you must implement the convert method of the org.apache.commons.beanutils.Converter interface. Here is the signature of the convert method.

public Object convert(Class type, Object value);

The first argument is the type to which you want to convert the object passed as the second argument. The method returns the result of conversion. The default converters can be found in the org.apache.commons.beanutils.converters package.

To register a custom converter, call the register method of the ConvertUtils class. The register method has the following signature:

public static void register(Converter converter, Class clazz);

For instance, If you have a converter that can convert a string to a date, you can call the register method this way:

ConvertUtils.register(java.util.Date.class, myDateConverter);

The app04b application is similar to app04a. However, the action class in app04b uses the BeanUtils class’s copyProperties method to copy an OrderForm instance to an OrderTO object. A custom converter is also written to allow BeanUtils to convert strings to dates.

The custom DateConverter class is given in Listing 4.6.

Listing 4.6: The DateConverter class

package app04b.util;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import org.apache.commons.beanutils.Converter;

public final class DateConverter implements Converter {
  private static SimpleDateFormat dateFormat;
  public DateConverter(String datePattern) {
    dateFormat = new SimpleDateFormat(datePattern);
    dateFormat.setLenient(false);
  }
  public Object convert(Class type, Object value) {
    try {
      return dateFormat.parse((String) value);
    }
    catch (ParseException e) {
    }
    return null;
  }
}

To construct a DateConverter object, you must specify a date pattern for this converter. The SaveOrderAction class in app04b, given in Listing 4.7, shows how to use the DateConverter class.

Listing 4.7: The app04b.action.SaveOrderAction class

package app04b.action;
import app04b.form.OrderForm;
import app04b.to.OrderTO;
import app04b.util.DateConverter;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;

public class SaveOrderAction extends Action {

  public ActionForward execute(ActionMapping mapping,
    ActionForm form, HttpServletRequest request,
    HttpServletResponse response) throws Exception {

    OrderForm orderForm = (OrderForm) form;
    OrderTO order = new OrderTO();
    ConvertUtils.register(new DateConverter("MM/dd/yyyy"),
      Date.class);
    BeanUtils.copyProperties(order, orderForm);

    // code for persisting the Order object goes here

    request.setAttribute("order", order);
    return (mapping.findForward("success"));
  }
}

Thanks to BeanUtils and our custom date converter, the SaveOrderAction in app04b is much shorter than the one in app04a.

Warning

While BeanUtils reduces the amount of code you need, mind you that it uses introspection extensively. Copying one single property goes through almost a hundred lines of code. It could take up to half a second to copy a bean’s property on my 2.8GHz machine.

Previous
Next