commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Kristian Mandrup" <krist...@mandrup.dk>
Subject Problems reading DynaBeans from xml using Betwixt
Date Sat, 27 Nov 2004 13:21:07 GMT
Hi all,

I have been trying to tweak betwixt to allow writing and reading of
DynaBeans. Betwixt currently only supports xml writing through a specialized
case in: 

XMLIntrospector.XMLBeanInfo introspect(Object bean)

if ( bean instanceof DynaBean ) 
...
            // this is DynaBean use the DynaClass for introspection
            return introspect( ((DynaBean) bean).getDynaClass() );
            
        } else {
            // normal bean so normal introspection

Looking at DynaClass interface:

public DynaClass getDynaClass();

DynaClass implementations only implements this getter, not any setters since
done in constructor (would be too dirty I guess!)

What is clearly needed is a setter to allow setting the dynaClass of the
bean when reading the bean from xml. Currently no dynaClass reference is
saved when writing the dynabean to xml, making it impossible to later
reconstruct the bean.

Obvious solution is to use the Adapter pattern. So I created my own
DynaBeanAdapter, DynaClassAdapter and DynaPropertyAdapter, including public
setter methods to allow reading the "dyna-info" from xml using betwixt...

Also created XMLDynaBeanIntrospector, dismissing special DynaBean behaviour.

In the end I get the following result:

String dynaBeanName = "dynabean";
String xmlStr = write(dynaBeanName, dynaBean);
DynaBeanAdapter dynaBeanM = (DynaBeanAdapter) read(xmlStr, dynaBeanName,
DynaBeanAdapter.class);
System.out.println("DynaBean:" + dynaBeanM);

String xmlStr2M = write(dynaBeanName, dynaClassM);
System.out.println("DynaClassM:" + xmlStr2M);


<?xml version='1.0' ?>  <dynaclass class="betwixt.DynaClassAdapter"
className="betwixt.DynaClassAdapter"
dynaBeanClass="org.apache.commons.beanutils.BasicDynaBean" name="Person"
id="1">
    <dynaProperties>
      <DynaPropertyAdapter class="betwixt.DynaPropertyAdapter"
className="betwixt.DynaPropertyAdapter" name="name" type="java.lang.String"
id="2"/>
      <DynaPropertyAdapter class="betwixt.DynaPropertyAdapter"
className="betwixt.DynaPropertyAdapter" name="age" type="java.lang.Integer"
id="3"/>
      <DynaPropertyAdapter class="betwixt.DynaPropertyAdapter"
className="betwixt.DynaPropertyAdapter" name="married"
type="java.lang.Boolean" id="4"/>
    </dynaProperties>
  </dynaclass>

betwixt.DynaClassAdapter@134e4fb
DynaClass:betwixt.DynaClassAdapter@134e4fb
<?xml version='1.0' ?>  <dynabean class="betwixt.DynaClassAdapter"
className="betwixt.DynaClassAdapter"
dynaBeanClass="org.apache.commons.beanutils.BasicDynaBean"
name="betwixt.DynaClassAdapter" id="1">
    <dynaProperties/>
  </dynabean>

As the result indicate, my reconstructed DynaClass object is EMPTY!!!


Problem seems to be, that the BasicDynaBean which I extend in my adapter
does not internally conform to the bean specifications:

protected DynaProperty properties[];
protected HashMap propertiesMap;

public DynaProperty getDynaProperty(String name);
public DynaProperty[] getDynaProperties();

How should I resolve this?

Tried add all these "adapter methods" in my DynaClassAdapter with no luck...
Not totally sure about how maps and arrays are handled in betwixt, the user
guide has very little info on these issues. How exactly are plurals resolved
in the above case. Should be handled by PluralStemmer, so I assume
properties in singular form becomes property!?

Class DynaClassAdapter {
...

    public DynaProperty getPropertiesMap(String name) {

        if (name == null) {
            throw new IllegalArgumentException
                    ("No property name specified");
        }
        return ((DynaProperty) propertiesMap.get(name));

    }    
    
    public void addDynaPropertiesMap(String name, DynaProperty property) {
        propertiesMap.put(name, property);
    }

    public void addDynaPropertyMap(String name, DynaProperty property) {
        propertiesMap.put(name, property);
    }
  
    public void setDynaProperties() {
        setProperties(properties);
    }
        
    public void setProperties(DynaProperty properties[]) {
        super.setProperties(properties);
    }

===
/*
 * Created on 2004-11-27 by @author Kristian
 * 
 */
package betwixt;

import org.apache.commons.beanutils.BasicDynaClass;
import org.apache.commons.beanutils.DynaProperty;

/**
 * Created on 2004-11-27 by @author Kristian
 * 
 * TODO Describe type
 * 
 */
public class DynaClassAdapter extends BasicDynaClass {

    /**
     * Comment for <code>serialVersionUID</code>
     */
    private static final long serialVersionUID = -6300500058450550700L;

    private String className = "betwixt.DynaClassAdapter";
    
    /**
     * @return Returns the className.
     */
    public String getClassName() {
        return className;
    }
    /**
     * @param className The className to set.
     */
    public void setClassName(String className) {
        this.className = className;
    }
    public DynaClassAdapter() {
        super();
    }

    public DynaClassAdapter(String name, Class dynaBeanClass,
            DynaProperty properties[]) {
        super(name, dynaBeanClass, properties);
    }
    
    public void setDynaBeanClass(Class dynaBeanClass) {
        super.setDynaBeanClass(dynaBeanClass);
    }

    public DynaProperty getPropertiesMap(String name) {

        if (name == null) {
            throw new IllegalArgumentException
                    ("No property name specified");
        }
        return ((DynaProperty) propertiesMap.get(name));

    }    
    
    public void addDynaPropertiesMap(String name, DynaProperty property) {
        propertiesMap.put(name, property);
    }
    
    public void addDynaPropertyMap(String name, DynaProperty property) {
        propertiesMap.put(name, property);
    }
    
  
    public void setDynaProperties() {
        setProperties(properties);
    }
        
    public void setProperties(DynaProperty properties[]) {
        super.setProperties(properties);
    }
    
}
===
/*
 * Created on 2004-11-27 by @author Kristian
 * 
 */
package betwixt;

import org.apache.commons.beanutils.DynaProperty;

/**
 * Created on 2004-11-27 by @author Kristian
 * 
 * TODO Describe type
 * 
 */
public class DynaPropertyAdapter extends DynaProperty {
    /**
     * Comment for <code>serialVersionUID</code>
     */
    private static final long serialVersionUID = 9105672480819027837L;

    private String className = "betwixt.DynaPropertyAdapter";
    
    public DynaPropertyAdapter() {
        super("noname");
    }

    public DynaPropertyAdapter(String name, Class type) {
        super(name, type);
    }    
    
    public void setName(String name) {
        this.name = name;  
    }
    public void setType(Class type) {
        this.type = type;
    }
  
    /**
     * @return Returns the className.
     */
    public String getClassName() {
        return className;
    }
    /**
     * @param className The className to set.
     */
    public void setClassName(String className) {
        this.className = className;
    }
}
===
/*
 * Created on 2004-11-27 by @author Kristian
 * 
 */
package betwixt;

import java.util.HashMap;

import org.apache.commons.beanutils.BasicDynaBean;
import org.apache.commons.beanutils.DynaClass;

/**
 * Created on 2004-11-27 by @author Kristian
 * 
 * TODO Describe type
 * 
 */
public class DynaBeanAdapter extends BasicDynaBean {

    /**
     * Comment for <code>serialVersionUID</code>
     */
    private static final long serialVersionUID = 1436974242229864237L;
    
    private DynaClass dynaClassRef;
    
    public DynaBeanAdapter() {
        super(null);
    }

    public DynaBeanAdapter(DynaClass dynaClass) {
        super(dynaClass);
        setDynaClassRef(dynaClass);
    }    
    
    /**
     * @return Returns the dynaClassRef.
     */
    public DynaClass getDynaClassRef() {
        return dynaClassRef;
    }
    /**
     * @param dynaClassRef The dynaClassRef to set.
     */
    public void setDynaClassRef(DynaClass dynaClassRef) {
        this.dynaClassRef = dynaClassRef;
        this.dynaClass = dynaClassRef;
    }
    /**
     * @return Returns the values.
     */
    public HashMap getValues() {
        return values;
    }
    /**
     * @param values The values to set.
     */
    public void setValues(HashMap values) {
        this.values = values;
    }    
}
===
/*
 * Created on 2004-11-27 by @author Kristian
 * 
 */
package betwixt;

import java.io.StringReader;
import java.io.StringWriter;

import org.apache.commons.beanutils.DynaProperty;
import org.apache.commons.betwixt.io.BeanReader;
import org.apache.commons.betwixt.io.BeanWriter;
import org.apache.commons.betwixt.strategy.PropertySuppressionStrategy;

/**
 * Created on 2004-11-27 by
 * 
 * @author Kristian
 * 
 * TODO Describe type
 *  @see commons-betwixt test DynaWithDotBetwixt, TestDynaBeanSupport (write
bean)
 *  Does not yet support reading DynaBeans...
 *  
 *  But must be possible to write DynaClass along with DynaBean and assemble
this way?
 *  
 *  
 */
public class DynaBeanApp {

    public static void main(String[] args) throws Exception {
        DynaPropertyAdapter name = new DynaPropertyAdapter("name",
String.class);
        DynaPropertyAdapter age = new DynaPropertyAdapter("age",
Integer.class);
        DynaPropertyAdapter married = new DynaPropertyAdapter("married",
Boolean.class);
        DynaProperty[] properties = new DynaProperty[] {name, age, married};
        DynaClassAdapter dynaClass = new DynaClassAdapter("Person", null,
properties);
        DynaBeanAdapter dynaBean = new DynaBeanAdapter(dynaClass);
        dynaBean.set("name", "Kristian Mandrup");
        dynaBean.set("age", new Integer(30));
        dynaBean.set("married", new Boolean(false));
        String dynaBeanName = "dynabean";
        String dynaClassName = "dynaclass";
//        String xmlStr = write(dynaBeanName, dynaBean);
        String xmlStr2 = write(dynaClassName, dynaClass);
        DynaClassAdapter dynaClassM = (DynaClassAdapter) read(xmlStr2,
dynaClassName, DynaClassAdapter.class);
        System.out.println("DynaClass:" + dynaClassM);
        String xmlStr2M = write(dynaBeanName, dynaClassM);
        System.out.println("DynaClassM:" + xmlStr2M);
        
        /*
        DynaBeanAdapter dynaBeanM = (DynaBeanAdapter) read(xmlStr,
dynaBeanName, DynaBeanAdapter.class);
        System.out.println("DynaBean:" + dynaBeanM);

        String xmlStrM = write(dynaBeanName, dynaBeanM);
        System.out.println("DynaBeanM:" + xmlStrM);
*/        
    }

    public static Object read(String xmlStr, String name,Class aclass)
throws Exception {
        // First construct the xml which will be read in
        // For this example, read in from a hard coded string
        StringReader xmlReader = new StringReader(xmlStr);
        
        // Now convert this to a bean using betwixt
        // Create BeanReader
        BeanReader beanReader  = new BeanReader();
        
        // Configure the reader
        // If you're round-tripping, make sure that the configurations are
compatible!
 
beanReader.getXMLIntrospector().getConfiguration().setAttributesForPrimitive
s(true);
        beanReader.getBindingConfiguration().setMapIDs(true);
        
        // Register beans so that betwixt knows what the xml is to be
converted to
        // Since the element mapped to a PersonBean isn't called the same, 
        // need to register the path as well
        beanReader.registerBeanClass(name, aclass);
        
        // Now we parse the xml
        Object obj = beanReader.parse(xmlReader);
        
        // send bean to system out
        System.out.println(obj);
        return obj;
    }
    
    public static String write(String name, Object obj) throws Exception {
        // Start by preparing the writer
        // We'll write to a string 
        StringWriter outputWriter = new StringWriter(); 
        
        // Betwixt just writes out the bean as a fragment
        // So if we want well-formed xml, we need to add the prolog
        outputWriter.write("<?xml version='1.0' ?>");
        
        // Create a BeanWriter which writes to our prepared stream
        BeanWriter beanWriter = new BeanWriter(outputWriter);
        beanWriter.setXMLIntrospector(new XMLDynaBeanIntrospector());
        // Configure betwixt
        // For more details see java docs or later in the main documentation
 
beanWriter.getXMLIntrospector().getConfiguration().setAttributesForPrimitive
s(true);
        beanWriter.getBindingConfiguration().setMapIDs(true);
        beanWriter.enablePrettyPrint();
        // do NOT suppress any properties
 
beanWriter.getXMLIntrospector().getConfiguration().setPropertySuppressionStr
ategy(
                new PropertySuppressionStrategy() {
                     public boolean suppressProperty(Class clazz, Class
type, String name) {
                         if ("indexed".equals(name) ||
"mapped".equals(name))
                             return true;
                         else return false;
                     }
                });

        
        
        beanWriter.write(name, obj);
        // Write to System.out
        // (We could have used the empty constructor for BeanWriter 
        // but this way is more instructive)
        String xmlStr = outputWriter.toString();
        System.out.println(xmlStr);
        return xmlStr;
    }
}

---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.779 / Virus Database: 526 - Release Date: 19-10-2004
 



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-user-help@jakarta.apache.org


Mime
View raw message