Thanks for responding (I get this in digest version, so I put your reply below)!
Actually, I do not need a full release; but I think that the Struts team does. I was using one of the release candidates with the intention of upgrading when they released 1.1 (which they did). The release candidate used BeanUtils 1.7... BUT, their final 1.1 release uses BeanUtils 1.6.1 (which makes sense, as they want to have all of the released code synced up). I did not realize this until quite a bit later and now I am stuck. I can't go to the released version of Struts 1.1 because I am using BeanUtilsBean, ConvertUtilsBean, and PropertyUtilsBean (which do not exist in BeanUtils 1.6.1).
My additions to them are REALLY simple, BUT do not make sense for the general public (otherwise, I would have posted them back). Basically (and I have attached all of my code), I subclassed BeanUtilsBean and PropertyUtilsBean just so that I could get my subclass of ConvertUtilsBean used (and, I think, to get access to some protected methods...). In my subclass of ConvertUtilsBean, I override the lookup(Class) method to see a property is of a specific base class (or array) and then substitute a different Converter for it.
It was so long ago that I did this, I do not remember why I was not able to just register this as a special converter (I do that already for things like Date and Boolean)... Anyway, it could be that I am doing something REALLY stupid that you - or someone else - would be able to spot in a second and, after having a good chuckle :-) , be able to suggest what I should do differently.
(If the attached Java classes get munged, just let me know if you want me to send them to you directly)
Thanks again! Allen
[ALLEN] If there are no current plans on releasing BeanUtils 1.7, can anyone give me advice on getting the classes above to work with a BeanUtils 1.6.1 release?
[ROBERT]
IMHO it would be very difficult to make those classes work without also adopting the other changes made since 1.6.1.
particular care is taken by all concerned over beanutils and the unit tests are maintained. i would have no issues with recommended the current HEAD as suitable for production with the proviso that the interfaces added since 1.6.1 are not guaranteed to be preserved in later 1.x series releases.
if you are unwilling to take my word for this, why not run a coverage tool over beanutils and create sufficient unit tests to ensure 100% coverage. this should be enough to give you confidence that the current features work.
is there any particular reason why you absolutely need a full release?
package gtri.p2d2.util.convert;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.beanutils.PropertyUtilsBean;
/**
* Done to allow access to the get instance method.
*
* @author Allen Servedio
* @version 1.0
*
* @since Phase 1 - Release 1
* @see gtri.p2d2.util.convert.ItdConvertUtilsBean
*/
public class ItdBeanUtilsBean extends BeanUtilsBean
{
/** Singleton instance */
private static final ItdBeanUtilsBean instance = new ItdBeanUtilsBean();
/** @return overridden to return an instance of this class */
protected static BeanUtilsBean getInstance()
{
return instance;
}
/**
* Default constructor.
*/
public ItdBeanUtilsBean()
{
this(ItdConvertUtilsBean.getInstance(), ItdPropertyUtilsBean.getInstance());
}
/**
* <p>Constructs an instance using given property and conversion instances.</p>
*
* @param convertUtilsBean use this <code>ConvertUtilsBean</code>
* to perform conversions from one object to another
* @param propertyUtilsBean use this <code>PropertyUtilsBean</code>
* to access properties
*/
public ItdBeanUtilsBean(ConvertUtilsBean convertUtilsBean, PropertyUtilsBean propertyUtilsBean)
{
super(convertUtilsBean, propertyUtilsBean);
}
}package gtri.p2d2.util.convert;
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.beanutils.ConvertUtils;
import itd.lib.bo.vo.MutableValueObject;
import itd.lib.bo.vo.ValueObject;
import itd.lib.struts.action.model.BaseActionForm;
import itd.lib.logger.Logger;
import itd.lib.logger.LoggerFactory;
/**
* Subclass of Jakarta Commons' ConverUtilsBean to deal with copying embedded value
* objects or action forms. Your value object and action form must use ITD library
* classes/interfaces, must conform to naming conventions, and must (for concrete
* classes) have a no-args constructor.
*
* <p>The value objects should implement one of these two interfaces: [EMAIL PROTECTED] itd.lib.bo.vo.MutableValueObject}
* or [EMAIL PROTECTED] itd.lib.bo.vo.ValueObject} and the action forms should inherit this
* class [EMAIL PROTECTED] itd.lib.struts.action.model.BaseActionForm}. </p>
*
* <p>There is no required naming convention for action forms, but the value object
* interfaces must end with VO (for the immutable interface) and VOMutable (for the
* mutable interface) and the concrete value object must be the same name as the iterfaces
* with the word Value in place of VO or VOMutable if interfaces are used (eg. AddressVO,
* AddressVOMutable, and AddressValue would be a valid set). If interfaces are not used, your value
* objects still have to implement one of the standard interfaces just so that they
* are reconized as value objects and have their properties recursively copied (there
* are no methods, so this should not be a problem).</p>
*
* @author Allen Servedio
* @version 1.0
*
* @since Phase 1 - Release 1
*/
public class ItdConvertUtilsBean extends ConvertUtilsBean
{
private static final Logger logger = LoggerFactory.getLogger(ItdConvertUtilsBean.class);
/** Default singleton */
private static final ItdConvertUtilsBean instance = new ItdConvertUtilsBean();
/** @return Get singleton instance - overridden to return a type of this object */
protected static ConvertUtilsBean getInstance()
{
return instance;
}
/**
* Default constructor
*/
public ItdConvertUtilsBean()
{
}
/**
* Converter for handling the special formatting for embedded value objects
* (a value object containing other value objects).
*/
protected static final Converter embeddedObjConverter = new Converter()
{
/**
* Convert the specified input object into an output object of the specified type.
*
* @param type Data type to which this value should be converted
* @param value The input value to be converted
* @return Converted the specified input object into an output object of the specified type.
* @throws ConversionException when there is a problem converting the object from one to another.
*/
public Object convert(Class type, Object value) throws ConversionException
{
Object result = value;
if (value != null && type != null)
{
try
{
// Look to see if the type is an array and if the value and type are
// an action form or value object. Regular arrays (like longs and strings)
// are handled by the base architecture.
Class typeCompType = type.getComponentType();
Class valueCompType = value.getClass().getComponentType();
if (type.isArray() && !typeCompType.isPrimitive() && value.getClass().isArray() && !valueCompType.isPrimitive() &&
(ValueObject.class.isAssignableFrom(valueCompType) || BaseActionForm.class.isAssignableFrom(valueCompType)
|| MutableValueObject.class.isAssignableFrom(valueCompType)))
{
Object[] list = null;
Object[] valueArr = ((Object[])value);
int len = valueArr.length;
if (len > 0)
{
Class arrType = type.getComponentType();
list = (Object[]) Array.newInstance(arrType, len);
for (int i = 0; i < len; i++)
{
list[i] = convert(arrType, valueArr[i]);
}
}
result = list;
}
else if (type.isArray() || value.getClass().isArray())
{
throw new UnsupportedOperationException("The embeddedObjConverter only works with action forms and value objects. Change lookup(...) method to use the default, not this one for a type array of '"
+typeCompType.getName() + "' with a value array of '"+valueCompType.getName()+"'.");
}
else
{
// If this is a mutable or immutable interface, assume a concreate class with the
// name Value in place of VO or VOMutable.
String name = type.getName();
if (type.isInterface() && (MutableValueObject.class.isAssignableFrom(type) || ValueObject.class.isAssignableFrom(type))
&& (name.endsWith("VO") || name.endsWith("VOMutable")))
{
String newClassName = name.substring(0, name.lastIndexOf("VO")) + "Value";
if (logger.isDebugEnabled())
{
logger.debug("Creating an instance of " + newClassName + " to store converted data for " + name);
}
Class newClass = Class.forName(newClassName);
result = newClass.newInstance();
}
else
{
result = type.newInstance();
}
ConversionInf conv = ConverterFactory.getConverterFactory().getConversion(value.getClass(), result.getClass());
if (conv != null)
{
conv.convert(value, result);
}
// This is a safety valve in case it cannot find the converter.
else
{
if (logger.isWarnEnabled())
{
logger.warn("Could not find conversion class for a conversion from " + result.getClass().getName()
+ " to " + value.getClass().getName() + " (using default copy properties instead).");
}
ItdBeanUtilsBean.getInstance().copyProperties(result, value);
}
}
}
catch (Throwable ex)
{
throw new ConversionException(ex);
}
}
return result;
}
};
/**
* Look up and return any registered [EMAIL PROTECTED] Converter} for the specified
* destination class; if there is no registered Converter, return
* <code>null</code>.
*
* @param clazz Class for which to return a registered Converter
*
* @return the converter for the class type.
*/
public Converter lookup(Class clazz)
{
Class typeCompType = clazz.getComponentType();
Converter result; // Do not initialize so that the IF statement must set it.
// Register a convert to deal with embedded value objects or action forms.
if (ValueObject.class.isAssignableFrom(clazz)
|| BaseActionForm.class.isAssignableFrom(clazz)
|| (clazz.isArray() && !typeCompType.isPrimitive() &&
(ValueObject.class.isAssignableFrom(typeCompType) || BaseActionForm.class.isAssignableFrom(typeCompType)
|| MutableValueObject.class.isAssignableFrom(typeCompType)))
|| MutableValueObject.class.isAssignableFrom(clazz))
{
result = embeddedObjConverter;
}
else
{
result = super.lookup(clazz);
}
return result;
}
}package gtri.p2d2.util.convert;
import org.apache.commons.beanutils.PropertyUtilsBean;
/**
* Done to allow access to the get instance method.
*
* @author Allen Servedio
* @version 1.0
*
* @since Phase 1 - Release 1
* @see gtri.p2d2.util.convert.ItdConvertUtilsBean, gtri.p2d2.util.convert.ItdBeanUtilsBean
*/
public class ItdPropertyUtilsBean extends PropertyUtilsBean
{
private static final ItdPropertyUtilsBean instance = new ItdPropertyUtilsBean();
/**
* @return instance of this class (even though type is for super class).
*/
protected static PropertyUtilsBean getInstance()
{
return instance;
}
/**
* Default constructor
*/
public ItdPropertyUtilsBean()
{
}
}
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
