| 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 |
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.