This works for marshalling, but has some quirks when unmarshalling. (Specifically, when unmarshalling the correct bean type is created, but none of the properties are initialized. I suspect this is because the AttributeDescriptor has no updaters, which may in turn be caused by some quirk when executing java.beans.Introspector on a subclass.)
import java.io.*; import java.util.*; import org.apache.commons.betwixt.*; import org.apache.commons.betwixt.digester.*; import org.apache.commons.logging.*; /** * * @author Jesse Sweetland */ public class HierarchalXMLIntrospector extends XMLIntrospector { /** Private, so we have to copy here */ private XMLBeanInfoDigester digester; protected synchronized XMLBeanInfo findByXMLDescriptor(Class c) { Set<Class> classes = new LinkedHashSet<Class>(); Class temp = c; while(temp != null) { classes.add(temp); for(Class ifc: temp.getInterfaces()) { classes.add(ifc); } temp = temp.getSuperclass(); } for(Class c2: classes) { String resourcePath = getResourcePath(c2); InputStream in = c2.getResourceAsStream(resourcePath); if(in != null) { try { configureDigester(c); return (XMLBeanInfo)digester.parse(in); } catch(Throwable t) { getLog().warn("Error parsing XML bean info resource " + resourcePath, t); } } } return null; } /** Private, so we have to copy here */ private synchronized void configureDigester(Class aClass) { if ( digester == null ) { digester = new XMLBeanInfoDigester(); digester.setXMLIntrospector( this ); } digester.setBeanClass( aClass ); } protected String getResourcePath(Class c) { return c.getName().substring(c.getName().lastIndexOf('.') + 1) + ".betwixt"; } }
To use this, just set the XMLIntrospector property on the BeanWriter:
BeanWriter bw = new BeanWriter(); bw.setXMLIntrospector(new HierarchalXMLIntrospector());