[ 
https://issues.apache.org/jira/browse/DIGESTER-133?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12664671#action_12664671
 ] 

niallp edited comment on DIGESTER-133 at 1/16/09 1:22 PM:
-------------------------------------------------------------------

The problem in BeanUtils was that the behaviour towards Maps that also have 
properties was inconsistent and the decision was taken to make everything 
consistent with the principle that "Maps are always treated as Maps". See 
BEANUTILS-162 for a full discussion on this.

As part of fixing that issue two methods were added to PropertyUtilsBean to 
make it easier for people to change this behaviour with their own custom 
implementation of PropertyUtilsBean:

 * getPropertyOfMapBean()  - See http://tinyurl.com/9jvjec
 * setPropertyOfMapBean() - See http://tinyurl.com/7d9ynj

So you can create your own PropertyUtilsBean implementation, something like the 
following

{code}
package org.myco.myproj;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.beanutils.PropertyUtilsBean;

public class MyPropertyUtilsBean extends PropertyUtilsBean {

    public static void initMyPropertyUtilsBean() {
        PropertyUtilsBean propertyUtils = new MyPropertyUtilsBean();
        ConvertUtilsBean convertUtils = new ConvertUtilsBean();
        BeanUtilsBean beanUtils = new BeanUtilsBean(convertUtils, 
propertyUtils);
        BeanUtilsBean.setInstance(beanUtils);
    }

    protected Object getPropertyOfMapBean(Map bean, String name)
        throws IllegalArgumentException, IllegalAccessException,
        InvocationTargetException, NoSuchMethodException {

        if (isReadable(bean, name)) {
            return getSimpleProperty(bean, name);
        } else {
            return super.getPropertyOfMapBean(bean, name);
        }
    }

    protected void setPropertyOfMapBean(Map bean, String name, Object value)
        throws IllegalArgumentException, IllegalAccessException,
               InvocationTargetException, NoSuchMethodException {
        if (isWriteable(bean, name)) {
            setSimpleProperty(bean, name, value);
        } else {
            super.setPropertyOfMapBean(bean, name, value);
        }
    }
}
{code}

I included a static method in the above to register your custom 
PropertyUtilsBean implementation

{code}
MyPropertyUtilsBean.initMyPropertyUtilsBean();
{code}

Then both BeanUtils and PropertyUtils should both delegate to your custom bean 
and get the behaviour you want.

      was (Author: niallp):
    The problem in BeanUtils is that the behaviour towards Maps that also had 
properties was inconsistent and the decision was taken to make everything 
consistent with the principle that "Maps are always treated as Maps". See 
BEANUTILS-162 for a full discussion on this.

As part of fixing that issue two methods were added to PropertyUtilsBean to 
make it easier for people to change this behaviour with their own custom 
implementation of PropertyUtilsBean:

 * getPropertyOfMapBean()  - See http://tinyurl.com/9jvjec
 * setPropertyOfMapBean() - See http://tinyurl.com/7d9ynj

So you can create your own PropertyUtilsBean implementation, something like the 
following

{code}
package org.myco.myproj;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import org.apache.commons.beanutils.PropertyUtilsBean;

public class MyPropertyUtilsBean extends PropertyUtilsBean {

    protected Object getPropertyOfMapBean(Map bean, String name)
        throws IllegalArgumentException, IllegalAccessException,
        InvocationTargetException, NoSuchMethodException {

        if (isReadable(bean, name)) {
            return getSimpleProperty(bean, name);
        } else {
            return super.getPropertyOfMapBean(bean, name);
        }
    }

    protected void setPropertyOfMapBean(Map bean, String name, Object value)
        throws IllegalArgumentException, IllegalAccessException,
               InvocationTargetException, NoSuchMethodException {
        if (isWriteable(bean, name)) {
            setSimpleProperty(bean, name, value);
        } else {
            super.setPropertyOfMapBean(bean, name, value);
        }
    }
}
{code}

You can then register your custom implementation in the following way:

{code}
        PropertyUtilsBean propertyUtils = new MyPropertyUtilsBean();
        ConvertUtilsBean convertUtils = new ConvertUtilsBean();
        BeanUtilsBean beanUtils = new BeanUtilsBean(convertUtils, 
propertyUtils);
        BeanUtilsBean.setInstance(beanUtils);
{code}

The both BeanUtils and PropertyUtils should both delegate to your custom bean 
and get the behaviour you want.
  
> Class fields are not set if class is inherited from HashMap if 
> commons-beanutils-1.8.0 is used
> ----------------------------------------------------------------------------------------------
>
>                 Key: DIGESTER-133
>                 URL: https://issues.apache.org/jira/browse/DIGESTER-133
>             Project: Commons Digester
>          Issue Type: Bug
>    Affects Versions: 1.6, 1.7, 1.8, 2.0
>         Environment: OS: Kubuntu 8.0.4, Java version is 1.5.0_15
> Windows XP, Java version 1.5.0_11-b03
>            Reporter: Alexander Kovalenko
>            Priority: Minor
>
> Class fields are not set if class is inherited from HashMap, value is put in 
> HashMap instead.
> I tried this simple test with  Digester 1.6, 1.7, 1.8 and 2.0. It works with 
> commons-beanutils-1.7.0, but does not work with commons-beanutils-1.8.0. 
> JUnit 4.4 was used for testing.
> ================ Class to be instantiated from XML ==========================
> import java.util.HashMap;
> public class MyClass extends HashMap<String, String> {
>       private boolean flag = false;
>       public boolean isFlag()
>       {
>               return flag;
>       }
>       public void setFlag(boolean flag)
>       {
>               this.flag = flag;
>       }
> }
> ================= Test ===================
> import static org.junit.Assert.assertTrue;
> import java.io.ByteArrayInputStream;
> import java.io.IOException;
> import org.apache.commons.digester.Digester;
> import org.junit.Test;
> import org.xml.sax.SAXException;
> public class TestDigester {
>       
>       @Test
>       public void testDigester() throws IOException, SAXException {
>               final String xml = "<myclass flag='true'/>";
>               
>               final Digester digester = new Digester();
>               digester.addObjectCreate("myclass", MyClass.class);
>               digester.addSetProperties("myclass");
>               
>               final MyClass res = (MyClass) digester.parse(new 
> ByteArrayInputStream(xml.getBytes()));
>               assertTrue(res.isFlag());
>       }
> }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to